Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
765 views
in Technique[技术] by (71.8m points)

Performance slowdown when using Julia's built-in functions

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Pardon the comment-for-an-answer, since I lack the rep to do a proper comment...

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).

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

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

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.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...