Julia 相互作用张量积分

Julia 相互作用张量积分,julia,integration,Julia,Integration,我需要计算以下积分,每个时间步长数千次: 地点和: ,及 到目前为止,我已经在Julia实施了: using StaticArrays function interactiontensor(C, a1, a2, a3, ϕ, θ) n1,n2 = 100,50 T = fill(0.0,3,3,3,3) Av = zeros(4,4) invAv = similar(Av) xi = Vector{Float64}(undef, 3) @inbo

我需要计算以下积分,每个时间步长数千次:

地点和:

,及

到目前为止,我已经在Julia实施了:

using StaticArrays

function interactiontensor(C, a1, a2, a3, ϕ, θ)

n1,n2   = 100,50
T       = fill(0.0,3,3,3,3)
Av      = zeros(4,4)
invAv   = similar(Av)
xi      = Vector{Float64}(undef, 3)


@inbounds  for p ∈ 1:n1        

    sinθp = sind(θ[p])
    cosθp = cosd(θ[p])
    for q ∈ 1:n2

        sinϕq  = sind(ϕ[q])
        cosϕq  = cosd(ϕ[q])            
        
        # -- Director cosines
        xi[1]  = sinθp*cosϕq/a1
        xi[2]  = sinθp*sinϕq/a2
        xi[3]  = cosθp/a3

        Christoffel!(Av,C,xi)
        fillAv!(Av, xi)

        invAv = inv(SMatrix{4,4}(Av))

        tensorT!(T,invAv,xi,sinθp)

        surface += sinθp
    end
end

return T ./= surface
end

@inline function Christoffel!(Av,C,xi)
@inbounds for t ∈ 1:3, r ∈ 1:3
    aux = zero(eltype(C))
    for u ∈ 1:3, s ∈ 1:3
        aux += C[r, s, t, u] * xi[s] * xi[u]        
    end
    Av[r, t] = aux
end
end

@inline function tensorT!(T,invAv,xi,sinθp)
@inbounds for k ∈ 1:3, i ∈ 1:3
    aux = invAv[i, k]
    for l ∈ 1:3, j ∈ 1:3
        T[i, j, k, l] += aux * xi[j] * xi[l] * sinθp
    end
end
end

@inline function fillAv!(Av, xi)
@inbounds for i ∈ 1:3
    xi0      = xi[i]
    Av[i, 4] = xi0
    Av[4, i] = xi0
end
end


考虑到我理想情况下需要计算此积分的次数,我的实现是否有任何优化,或者是否有其他方法可以大大降低计算成本?

以下是一些建议:

  • sinθp,cosθp=sincosd(θ[p])
    ,即一步计算正弦和余弦
  • xi=@SVector zero(3)
    初始化为静态向量,然后用于分配每次迭代中的值,即
    @set x[1]=sinθp*cosñq/a1
  • 加载包并使用
    @avx
    宏(非常粗略地说,类似于
    @simd
    )来加速
    Christoffel中的循环
    tensorT
    fillAv
在我的机器上,我发现这些更改将计算时间减少了5倍以上(相对于OP中的原始函数)。最大的部分是由于
@avx
,上面的第二点约占30%

julia> @btime interactiontensor_original($C, $10.0, $5.0, $1.0, $ϕ, $θ);
  661.655 μs (5 allocations: 1.28 KiB)

julia> @btime interactiontensor_optimized($C, $10.0, $5.0, $1.0, $ϕ, $θ);
  125.352 μs (4 allocations: 1.17 KiB)
这里是完整的修改代码(注意,我注释掉了OP中未指定的涉及
surface
的行):


你根本不是瓶颈,但你可以写得更快的
sinθp,cosθp=sincosd(θ[p])
。既然你明确地写出了收缩,你可能想试试
@simd
。或者,尝试一个Einsum包,如,或。是否可以分析计算
A(θ,ν)
的逆?您是否尝试过避免显式计算
inv
,而是在
tensorT内使用
\
?通过制作<代码>席=@向量零(3)< /代码>,然后使用设置席的组成部分,即“代码> > SET X [1 ] = Sin Th P*CoS Q/A1 < /代码> FIY,<代码> @界内@ AVX冗余,可以加快(30%)在我的机器上的速度。
@avx
中的所有数组访问都已隐式位于边界内。它会禁用所有安全功能谢谢,很高兴知道!我会更新我的答案。
julia> @btime interactiontensor_original($C, $10.0, $5.0, $1.0, $ϕ, $θ);
  661.655 μs (5 allocations: 1.28 KiB)

julia> @btime interactiontensor_optimized($C, $10.0, $5.0, $1.0, $ϕ, $θ);
  125.352 μs (4 allocations: 1.17 KiB)
using StaticArrays, Setfield, LoopVectorization

function interactiontensor_optimized(C, a1, a2, a3, ϕ, θ)

    n1,n2   = 100,50
    T       = fill(0.0,3,3,3,3)
    Av      = zeros(4,4)
    invAv   = similar(Av)
    xi      = @SVector zeros(3)


    @inbounds for p ∈ 1:n1

        sinθp, cosθp = sincosd(θ[p])
        for q ∈ 1:n2

            sinϕq, cosϕq  = sincosd(ϕ[q])

            # -- Director cosines
            @set xi[1]  = sinθp*cosϕq/a1
            @set xi[2]  = sinθp*sinϕq/a2
            @set xi[3]  = cosθp/a3

            Christoffel!(Av,C,xi)
            fillAv!(Av, xi)

            invAv = inv(SMatrix{4,4}(Av))

            tensorT!(T,invAv,xi,sinθp)

            # surface += sinθp
        end
    end

    return T #./= surface
end

@inline function Christoffel!(Av,C,xi)
    @avx for t ∈ 1:3, r ∈ 1:3
        aux = zero(eltype(C))
        for u ∈ 1:3, s ∈ 1:3
            aux += C[r, s, t, u] * xi[s] * xi[u]
        end
        Av[r, t] = aux
    end
end

@inline function tensorT!(T,invAv,xi,sinθp)
    @avx for k ∈ 1:3, i ∈ 1:3
        aux = invAv[i, k]
        for l ∈ 1:3, j ∈ 1:3
            T[i, j, k, l] += aux * xi[j] * xi[l] * sinθp
        end
    end
end

@inline function fillAv!(Av, xi)
    @avx for i ∈ 1:3
        xi0      = xi[i]
        Av[i, 4] = xi0
        Av[4, i] = xi0
    end
end