Julia 中对称矩阵的快速求和

mat*_*nor 3 julia

我想将A维度为ntimes 的矩阵中的所有元素相加n。该矩阵是对称的并且对角线上有 0。我发现最快的方法很简单 sum(A)。然而,这似乎很浪费,因为它没有利用我只需要计算矩阵的下三角形的事实。然而,sum(tril(A, -1))速度明显慢得多,甚至sum(A[i, j] for i = 1:n-1 for j = i+1:n)更慢。有没有更有效的方法来求和矩阵?

编辑:@AboAmmar 的解决方案表现良好。下面是要比较的代码(分别对对角线求和,如果对角线上只有零,则可以删除某些内容):

using BenchmarkTools
using LinearAlgebra

function sum_triu(A)
    m, n = size(A)
    @assert m == n
    s = zero(eltype(A))
    for j = 2:n
        @simd for i = 1:j-1
            s += @inbounds A[i,j]
        end
    end
    s *= 2
    for i = 1:n
        s += A[i, i]
    end
    return s
end

N = 1000
A = Symmetric(rand(0:9,N,N))
A -= diagm(diag(A))

@btime sum(A)
@btime 2 * sum(tril(A))
@btime sum_triu(A)
Run Code Online (Sandbox Code Playgroud)

Abo*_*mar 5

这比sumn = 1000 矩阵快 2.7 倍。确保添加一个@simd在循环之前添加 a 并使用@inbounds. 另外,使用正确的循环顺序来实现快速内存访问。

\n
function sum_triu(A)\n    m, n = size(A)\n    @assert m == n\n    s = zero(eltype(A))\n    for j = 1:n\n        @simd for i = 1:j \n            s += @inbounds A[i,j]\n        end\n    end\n    return 2 * s\nend\n
Run Code Online (Sandbox Code Playgroud)\n

在我的电脑上运行的示例:

\n
sum_triu(A) = 499268.7328022966\nsum(A) = 499268.73280229873\n   93.000 \xce\xbcs (0 allocations: 0 bytes)\n  249.900 \xce\xbcs (0 allocations: 0 bytes)\n
Run Code Online (Sandbox Code Playgroud)\n