6 ms·
I had a lot of experience a few years ago with Julia, having ported a lot of my numerical code in the language. I ended up severely disappointed with it for mod
by unfamiliar 9y ago
I had a lot of experience a few years ago with Julia, having ported a lot of my numerical code in the language. I ended up severely disappointed with it for moderately complex numerical computing projects.
The language was really nice; the problem was terrible performance, and I believe that this was caused by bad design of the memory semantics. Even in optimised code, there were temporary objects and copies all over the place, and they were very hard to eliminate without resorting to using global arrays everywhere.
- vanderZwan 9y ago> Even in optimised code, there were temporary objects and copies all over the place, and they were very hard to eliminate without resorting to using global arrays everywhere. Could you elaborate a bit with some examples, because this goes against everything I understand about the strengths of the language: (without having used it beyond a few first examples myself) - you can define types and operations on them down to the bits themselves, giving you a lot of control over the memory (and definitely a lot more than Python) - it has a lot of support for in-place mutation out of the box - globals are almost always bad news for performance Sure, adding two arrays with C = A + B .. produces an intermediate array, yes, but if you know A and B are not reused, wouldn't using: A += B C = A .. instead be enough?
- ffriend 9y agoEven better would be to write (see dot vectorization [1]): C .= A .+ B Benchmarks for 3 matrices of size 1000x1000: julia> using BenchmarkTools julia> @benchmark C = A + B BenchmarkTools.Trial: memory estimate: 7.63 MiB allocs estimate: 2 -------------- minimum time: 2.359 ms (0.00% GC) median time: 2.713 ms (0.00% GC) mean time: 3.794 ms (28.81% GC) maximum time: 62.708 ms (95.27% GC) -------------- samples: 1314 evals/sample: 1 julia> @benchmark C .= A .+ B BenchmarkTools.Trial: memory estimate: 128 bytes allocs estimate: 4 -------------- minimum time: 1.232 ms (0.00% GC) median time: 1.320 ms (0.00% GC) mean time: 1.356 ms (0.00% GC) maximum time: 2.572 ms (0.00% GC) -------------- samples: 3651 evals/sample: 1 Note that memory usage dropped from 7.63MiB to 128 bytes. [1]: https://docs.julialang.org/en/stable/manual/functions/#man-vectorized-1 https://docs.julialang.org/en/stable/manual/functions/#man-v...
- vanderZwan 9y agoThanks! Like I said: I never truly dove into it, although I loved reading about the approach to the type system, and the multiple dispatch. > Note that memory usage dropped from 7.63MiB to 128 bytes. Which is important if you're working with large data-sets. Both for performance and for being able to run the calculations at all.
- stabbles 9y agoA little bit late to the party here, but the number of allocations is really just 0 bytes. It shows 128 bytes because the benchmark is creating new references to A, B and C. To correct this use either interpolation with $A, $B and $C or initialize A, B and C in the setup phase: > @benchmark C .= A .+ B setup = (A = rand(1000, 1000); B = rand(1000, 1000); C = rand(1000, 1000)) BenchmarkTools.Trial: memory estimate: 0 bytes allocs estimate: 0 -------------- minimum time: 2.048 ms (0.00% GC) This is showing 0 bytes indeed.
- dagw 9y agoI had exactly the same experience. Julia's JIT compiler is (or at least was) really picky to what code it did and didn't like. Two pieces of which look 'basically' the same can have a performance difference of an order of magnitude due to the JIT liking one version and not the other.
- jernfrost 9y agoHow do you know that the code was optimized for Julia? Your poor results suggests you are simply not familiar with how to optimize in Julia. E.g. did you check type stability with type_warn() ?
- rrock 9y agoI had exactly the opposite experience. If you were having problems with temporaries, you were probably using Matlab style vectorized operations. Back when you tried Julia, explicit loops could avoid this allocation issue. Now, Julia has syntactic broadcast operators which will fuse loops for you. See https://julialang.org/blog/2017/01/moredots https://julialang.org/blog/2017/01/moredots