Measurements.jl
Measurements.jl copied to clipboard
Arithmetic operations very slow
upd 2025: see Uncertain.jl for fast error propagation that ignores correlations
It looks like this package has a lot of overhead for simple math operations - about 50 times slower than normal floats and uses 20 times more memory! Not even talking about number of allocations.
using BenchmarkTools
using Measurements
a = randn(1000, 1000)
b = randn(1000, 1000)
@btime a ./ b;
# 1.791 ms (4 allocations: 7.63 MiB)
a, b = a .± b, b .± a
@btime a ./ b;
# 88.498 ms (4000004 allocations: 175.48 MiB)
For comparison, an extremely basic implementation from rosettacode has only 4x overhead, which is completely reasonable:
using Main.NumericError
a = randn(1000, 1000)
b = randn(1000, 1000)
a, b = Measure.(a, b), Measure.(b, a)
@btime a ./ b;
# 6.797 ms (4 allocations: 15.26 MiB)
Any chance that performance of Measurements.jl can be improved?
Yes, I'm aware that for large calculations the performance is not ideal. Try computing the mean of a large vector :persevere: However, for a large set of uncorrelated measurements there is the weightedmean functions which is much faster and probably what the user is after.
The extremely basic implementation from rosettacode is fast because it doesn't deal with correlation:
julia> x1 = Measure(100, 1.1) # from rosettacode
100.0 ± 1.1
julia> x1-x1
0.0 ± 1.5556349186104046
julia> x = measurement(100, 1.1) # from this package
100.0 ± 1.1
julia> x-x
0.0 ± 0.0
Dealing with correlation is the main source of the overhead. I prefer something slow but correct to something fast but unreliable.
Any chance that performance of Measurements.jl can be improved?
Not from me, currently, but patches are always welcome :slightly_smiling_face: The important thing is that functionalities are maintained, this should be an under-the-hood only change. I've the feeling that performance can be improved, but I've never looked into this very deeply. Thanks for opening this issue!
I see, correlations indeed can be quite important and it is far from obvious how to speed up calculations while maintaining them. However it would be useful to have another mode (or type, or something) for fast computations without tracking correlations. For even moderately-sized datasets x50 slowdown is very significant, and what is often needed is just simple uncertainty propagation with independent observations.
what is often needed is just simple uncertainty propagation with independent observations
It's not that simple. If x is a measurement, f(x) is a quantity correlated with x, then if you perform calculations involving both x and f(x) (or another quantity derived from x) you have to take care of correlation between them. Correlation is not important only if you're going to perform a single operation with a one-argument only function, and then stop
However it would be useful to have another mode (or type, or something) for fast computations without tracking correlations.
I see your point, and it shouldn't be too hard to implement what you ask, but in my opinion its utility would be very limited (see above message) and would greatly confuse users (which type should I use? With correlation or not? What if I later change my mind?).
Some overhead compared to plain-bit numbers is to be expected, this type is going to do much more than adding or multiplying simple Float64 numbers. Large overhead comes when several quantity are involved, performance of calculations involving Measurement objects currently goes as O(n^2). It would be really great if someone could find a way to improve performance to O(n).