【问题标题】:Alternatives to `for` loops in this context in Julia在 Julia 的上下文中替代 `for` 循环
【发布时间】:2021-10-26 16:24:21
【问题描述】:

我在 Julia 中有一个矩阵,其中包含 0,1 作为元素。假设我考虑第 i 行(随机),然后我想遍历行的所有元素,对于元素为 1 的列 j,我想执行涉及不同列表的元素 i,j 的算术运算。我希望为矩阵中所有可能的“j”列完成此操作。目前我有以下代码用于 NxN 方阵mat

e = 0
for j in (1:N)
     if mat[i,i] == 1 
          e += -(list[i]*list[j])
     end
end

但是,我需要一遍又一遍地为相当大的矩阵执行此操作,因此我想知道是否有更快的方法来执行此操作。我想我也许可以使用Iterators,但我真的不知道该怎么做。

【问题讨论】:

  • Julia 中的循环速度很快,因此您无需寻找“特殊的内置”功能即可获得良好的性能。精心设计的循环通常是您最好的选择。但是,您应该确保以有效的模式遍历数组(记住 Julia 中的列优先数组!)。除此之外,您的示例还不够完整,无法轻松提出更详细的建议。也许你可以添加一个合适的 MWE?

标签: performance for-loop iteration julia


【解决方案1】:

Julia 将能够很好地优化该代码,但我们可以在一定程度上简化和提高性能。既然您提到了迭代器,让我们从使用迭代器理解的解决方案开始,我们使用sum 对值求和并分解出公因子list[i]

list[i]*sum(list[j] for j in 1:length(list) if mat[i,j] == 1)

这或多或少被朱莉娅解释为:

-list[i]*sum(Iterators.map(j->list[j], Iterators.filter(j -> mat[i,j] == 1, 1:length(list))))

但理解更简洁,您可能看起来更熟悉。

这比原来的性能略高(节省 20%-30% 的时间),但是,迭代器通常不是最快的解决方案,除非内存是瓶颈。让我们尝试广播:

-list[i]*sum(list[mat[i,:] .== 1])

这进一步提高了性能(在我的测试中比原来节省了 40%)。

我们不需要mat[i,:] 的副本,所以让我们使用视图:

list[i]*sum(list[@view(mat[i,:]) .== 1])

现在我们已经削减了 50% 以上。当然,只使用一个产品可能更简单(因为我们有 0 和 1)并且性能相似:

-list[i]*sum(list .* mat[i,:])

如果您可以以不同的方式排列数据,则应该可以进一步提高性能,例如使用 BitMatrix 代替数字并使用转置矩阵,因此我们迭代列而不是行(因为 Julia 使用列优先顺序)。

基准测试:

using BenchmarkTools

function original(mat, list, i)
    N = length(list)
    e = 0
    for j in (1:N)
         if mat[i,j] == 1
              e += -(list[i]*list[j])
         end
    end
    e
end

function sol1(mat, list, i)
    -list[i]*sum(list[j] for j in 1:length(list) if mat[i,j] == 1)
end

function sol2(mat, list, i)
    -list[i]*sum(list[mat[i,:] .== 1])
end

function sol3(mat, list, i)
    -list[i]*sum(list[@view(mat[i,:]) .== 1])
end

function sol4(mat, list, i)
    -list[i]*sum(list .* mat[i,:])
end

mat = rand(0:1, 1000, 1000)
list = rand(1000)
i = rand(1:1000)

@btime original($mat, $list, $i)
@btime sol1($mat, $list, $i)
@btime sol2($mat, $list, $i)
@btime sol3($mat, $list, $i)
@btime sol4($mat, $list, $i)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多