我一直在试图在Julia中使用静态数组,但却一直碰壁。
https://github.com/JuliaArrays/StaticArrays.jl
他们很快,但更新它们很麻烦。这并不奇怪,因为它们本来就是不可变的!但是一直有人建议我即使需要更新它们也使用静态数组。在我的情况下,静态数组很小,只有长度为3,我有一个它们的向量,但我每次只更新一个长度为3的SVector。
选项1
有一个非常棒的包叫做Setfield
,它允许您在Julia中进行SVectors的就地更新。
https://github.com/jw3126/Setfield.jl
抓住问题......它更新本地副本。因此,如果您在嵌套函数中,则会更新本地副本。因此,需要进行一些簿记,因为您必须就地更新本地副本,然后return
该副本并更新实际感兴趣的数组。您无法传入所需的数组并直接更新它,至少我找不到方法!现在,我不介意簿记,但我觉得更新本地副本,然后返回值,更新另一个本地副本,然后返回值,最后更新实际数组必须带来速度惩罚。我可能错了。
选项2
让我感到困扰的是,为了更新静态数组,我必须执行以下操作:
exampleSVector::SVector{3,Float64}
<-- 只是为了明确其类型和大小
exampleSVector = [value1, value2, value3]
这将更新所需的数组,即使它在函数内部,这很好并且是目标,但如果您在函数内部执行此操作,则会创建一个临时数组。这让我很烦恼,因为我的函数在循环中被调用了400万次以上,因此这会产生大量分配并减慢速度。
我如何在不创建临时数组的情况下更新选项2场景下的SVector?对于选项1场景,我能否更新实际感兴趣的数组而不是本地副本?如果需要一个简单的示例代码,请在评论中说明,我会制作一个。我的想法是可以回答这个问题,但如果需要,我会制作一个示例代码。
编辑:MCVE代码-选项1可行,选项2不可行。
using Setfield
using StaticArrays
struct Keep
dreaming::Vector{SVector{3,Float64}}
end
function INNER!(vec::SVector{3,Float64},pre::SVector{3,Float64})
# pretend series of calculations
for i = 1:3 # illustrate use of Setfield (used in real code for this)
pre = @set pre[i] = rand() * i * 1000
end
# more pretend calculations
x = 25.0 # assume more calculations equals x
################## OPTION 1 ########################
vec = @set vec = x * [ pre[1], pre[2], pre[3] ] # UNCOMMENT FOR FOR OPTION 1
return vec # UNCOMMENT FOR FOR OPTION 1
################## OPTION 2 ########################
#vec = x * [ pre[1], pre[2], pre[3] ] # UNCOMMENT FOR FOR OPTION 2
#nothing # UNCOMMENT FOR FOR OPTION 2
end
function OUTER!(always::Keep)
preAllocate = SVector{3}(0.0,0.0,0.0)
for i=1:length(always.dreaming)
always.dreaming[i] = INNER!(always.dreaming[i], preAllocate) # UNCOMMENT FOR FOR OPTION 1
#INNER!(always.dreaming[i], preAllocate) # UNCOMMENT FOR FOR OPTION 2
end
end
code = Keep([zero(SVector{3}) for i=1:5])
OUTER!(code)
println(code.dreaming)
SVector
呢?对于第二个选项,你可以写成exampleSVector = SVector(value1, value2, value3)
,这样就不需要分配内存了。在你的 MCVE 代码中,只需写成vec = vec .* x
即可。顺便说一句:vec
是 Base 库中的函数名称,你不应该将其覆盖。 - DNFMVector
的速度并不比SVector
慢太多。在某些情况下它们几乎是相似的。(实际上,你也可以用vec *= x
来代替vec = vec .* x
。) - DNF