Julia 相互作用张量积分
我需要计算以下积分,每个时间步长数千次: 地点和: ,及 到目前为止,我已经在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
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代码>
@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