我是 julia 的新手,为了开始,我想将一些 numpy 代码移植到 julia,并希望获得一些不错的性能提升。到目前为止,我并不满意。
这是我想要计算的函数
function s(x_list, r_list)
result_list = zeros(size(x_list,1))
for i = 1:size(x_list,1)
dotprods = r_list * x_list[i,:]'
expcall = exp(im * dotprods)
sumprod = sum(expcall) * sum(conj(expcall))
result_list[i] = sumprod
end
return result_list
end
数据输入看起来像
v = rand(3)
r = rand(6000,3)
x = linspace(1.0, 2.0, 300) * (v./sqrt(sumabs2(v)))'
对于这个函数和给定的输入,@time s(x,r)
给了我
0.110619 seconds (3.60 k allocations: 96.256 MB, 8.47% gc time)
对于这种情况,numpy 在 ~70ms 内完成相同的工作,所以我不是很开心!现在,如果我用julia -p 2
做一个@parallel for
循环:
function s(x_list, r_list)
result_list = SharedArray(Float64, size(x_list,1))
@parallel for i = 1:size(x_list,1)
dotprods = r_list * x_list[i,:]'
expcall = exp(im * dotprods)
sumprod = sum(expcall) * sum(conj(expcall))
result_list[i] = sumprod
end
return result_list
end
问题是
result_list[i] = sumprod
没有得到更新,我得到了数组初始化返回的零列表。我在这里做错了什么?进一步尝试提高速度也没有显示出任何好处,例如
@vectorize_2arg Array{Float64,2} s
和声明类型
function s{T<:Float64}(x_list::Array{T,2}, r_list::Array{T,2})
但是现在,在只有一个线程(没有-p2
,只是julia
)的会话中启动相同的@parallel for
循环,数组确实会更新,@time s(x,r)
告诉我
0.000040 seconds (36 allocations: 4.047 KB)
对于给定的功能和输入来说,这实际上是不可能的!这是一个错误吗?
任何帮助都非常感谢!
Julia的@parallel
宏执行分布式for循环:它将所有数据复制到其他进程,并对每个进程进行计算,减少结果并返回该结果。这些进程不共享内存,甚至可能完全在其他计算机上。您的原始数据永远不会被触及,因为每个工作人员都在修改自己的数据副本。您可能正在考虑线程,这是Julia将来将添加的当前实验性功能。
一个问题是您没有等待@parallel
调用完成。从文档中:
。如果不需要归约运算符,可以省略它。在这种情况下,循环异步执行,即它在所有可用的工作线程上生成独立的任务,并立即返回 Future 数组,而无需等待完成。调用方可以通过调用
fetch()
来等待稍后的 Future 完成,或者通过在循环末尾加上@sync
前缀来等待完成,例如@sync @parallel for
。
尝试在循环的前缀加上@sync