使用Julia的内置功能时性能降低 [英] Performance slowdown when using Julia's built-in functions
问题描述
我所属的一个研究小组最近决定尝试从我们以前的编码语言迁移到Julia,因为除其他因素外,与其他用户友好语言相比,该语言声称具有高速性能.但是,在我们的代码片段的初始翻译中,我的一位合作伙伴注意到与使用简单的循环技术相比,使用Julia的内置函数(特别是诸如"find"之类的相当简单的函数)会导致速度降低大约十倍.有没有其他人遇到过这个问题,或者还有其他可能的原因值得我们研究吗?
A research group I am a part of has recently decided to try migrating to Julia from our previous coding language, because of, among other things, its claimed high-speed performance as compared to other user-friendly languages. However, in our initial translations of code snippets, one of my partners noticed that using Julia's built-in functions (specifically rather simple ones such as 'find') causes about a tenfold drop in speed as compared to using simple looping techniques. Has anyone else encountered this, or are there other probable causes we should look into?
推荐答案
请原谅我的评论,因为我缺少代表来发表适当的评论...
Pardon the comment-for-an-answer, since I lack the rep to do a proper comment...
我对Julia的了解是,如果您为了获得最佳性能而钓鱼,通常最好编写循环.这已经有一段时间了.请参见林大华的有关对向量进行向量化的帖子. (,但将来可能会改变;请参阅Colin T. Bowers关于多线程的讨论
What I understand about Julia is that it is usually better to write loops if you are fishing for maximum performance. This has been true for quite a while; see, e.g., Dahua Lin's post about devectorizing expressions. (edit: but it may change in the future; see Colin T. Bowers' discussion about multithreading here and in comment below).
请记住,判断性能可能很棘手.实际上,我在自己的代码中经常使用find
,因为我可以在不太长的稀疏" Vector
中简洁地要求非零的Int
索引.与等效循环相比,find
相对灵活,快速且清晰.例如:
Keep in mind that judging performance can be tricky. I actually use find
a lot in my own code since I can succinctly ask for the Int
indices of the nonzeroes in a "sparse" Vector
that is not obscenely long. find
is relatively flexible, speedy, and clear compared to an equivalent loop. For example:
# problem dimensions
p = 10000
k = 10
# a "sparse" vector with k random nonzeroes
b = zeros(p)
b[1:k] = randn(k)
shuffle!(b)
# use `find` to get the indices
@time bidx = find( x -> x .!= 0.0, b)
# is `find` faster than looping?
function find_nonzeroes(b, k)
bnz = zeros(Int,k);
j = 0
@inbounds for i = 1:length(b)
if b[i] .!= 0.0
j += 1
bnz[j] = i
end
j >= k && break
end
return bnz
end
@time bnz = find_nonzeroes(b, k);
# are results same?
println("Return arrays equal? ", isequal(bidx,bnz))
在我的机器上,两次运行全部之后,结果是:
On my machine, after running everything twice, the results are:
0.001795 seconds (10.03 k allocations: 158.402 KB)
0.004593 seconds (2.57 k allocations: 131.876 KB)
Return arrays equal? true
但是,如果您增大b
的尺寸,例如对p = 1000000
说,那么结果会大不相同:
But if you jack up the dimension of b
, say to p = 1000000
, then the results are quite different:
0.028236 seconds (1.00 M allocations: 15.261 MB, 7.70% gc time)
0.005493 seconds (2.57 k allocations: 131.876 KB)
Return arrays equal? true
find_nonzeores
函数比find
更复杂,灵活性更差,但可以更好地扩展到更高的p
.在高维上,权衡可能是值得的,尤其是如果您经常在代码中调用find
时.
The find_nonzeores
function is more convoluted and less flexible than find
, but it scales better to higher p
. In high dimensions the tradeoff may be worth it, especially if you often call find
in your code.
由于您没有提供有关移植到Julia的详细信息,因此很难为您提供更具体的建议. 性能提示上的Julia页面是我的首选参考,并重新阅读它通常可以帮助我提高代码的速度.
Since you offer no details about what you ported to Julia, then it is difficult to offer you any more specific advice than that. The Julia page on performance tips is my go-to reference, and re-re-re-reading it has often helped me improve my code's speed.
这篇关于使用Julia的内置功能时性能降低的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!