在行上迭代矩阵的推荐方法是什么?

时间:2014-02-14 11:37:57

标签: julia

给定一个矩阵m = [10i+j for i=1:3, j=1:4],我可以通过切割矩阵迭代它的行:

for i=1:size(m,1)
    print(m[i,:])
end

这是唯一的可能性吗?这是推荐的方式吗?

那么理解呢?切片是否唯一可能迭代矩阵的行?

[ sum(m[i,:]) for i=1:size(m,1) ]

3 个答案:

答案 0 :(得分:47)

您自己列出的解决方案以及mapslices都可以正常工作。但如果通过“推荐”你真正的意思是“高性能”,那么最好的答案是:不要遍历行。

问题在于,由于数组以列主要顺序存储,对于除小矩阵以外的任何其他内容,如果以行主顺序遍历数组,则最终会导致穷cache hit ratio

正如在excellent blog post中指出的那样,如果你想对行进行求和,最好的办法就是做这样的事情:

msum = zeros(eltype(m), size(m, 1))
for j = 1:size(m,2)
    for i = 1:size(m,1)
        msum[i] += m[i,j]
    end
end

我们以其本机存储顺序遍历mmsum,因此每次加载缓存行时,我们都使用所有值,产生的缓存命中率为1.您可能天真地认为它是最好以行主顺序遍历它并将结果累加到tmp变量,但在任何现代机器上,缓存未命中都比msum[i]查找要贵得多。

Julia的许多采用region参数的内部算法(如sum(m, 2))会为您处理此问题。

答案 1 :(得分:3)

根据我的经验,显式迭代比理解快得多。

迭代列也是一个很好的建议。

此外,您可以使用新的宏@simd和@inbounds来进一步加速它。

答案 2 :(得分:2)

从Julia 1.1开始,有迭代器实用程序可用于迭代矩阵的列或行。要遍历行:

M = [1 2 3; 4 5 6; 7 8 9]

for row in eachrow(af)
    println(row)
end

将输出:

[1, 2, 3]
[4, 5, 6]
[7, 8, 9]