# @turbo macro giving slightly different results

**URL:** <https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529>\
**Category:** General Usage\
**Tags:** loopvectorization\
**Created:** [January 25, 2023, 7:00pm UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529 "2023-01-25T19:00:36Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shashank](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shashank/32/12323_2.png) [@Shashank](https://discourse.julialang.org/u/Shashank)\
**Post date:** [January 25, 2023, 7:00pm UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/1 "2023-01-25T19:00:37Z")

</div>

I am trying to vectorize a loop, and adding the turbo gives slightly different results. The code does not rely on specific execution order as is the case with the example in the post below:

> [@@turbo macro gives incorrect results](https://discourse.julialang.org/t/turbo-macro-gives-incorrect-results/89280):
>
> I often use the @turbo macro for calculations. But I recently discovered that using it sometimes gives incorrect results. Below are minimal working examples where different options are compared. using LoopVectorization tbuf = [0.0, 0.0] tbuf2 = [0.0, 0.0] tbuf3 = [0.0, 0.0] @turbo for i = 1:length(tbuf) tbuf[i] = 1.0 tbuf[i] += 1.0 tbuf[i] \*= -1.0 end @inbounds @simd for i = 1:length(tbuf2) tbuf2[i] = 1.0 tbuf2[i] += 1.0 tbuf2[i] \*= -1.0 end @inbounds for i =…

I have pasted a MWE below. Are such small differences expected due to @turbo, or am I doing something wrong?

```julia
using LoopVectorization
global ans1 = 0.0e0
@turbo for i = 1:1000000
    ans1=ans1+sqrt(i)
end
println(ans1)
    
global ans2=0.0e0

for i = 1:1000000
    global ans2
    ans2=ans2+sqrt(i)
end
println(ans2)
println(ans1-ans2)

```

The output on my computer is as follows:

6.666671664588217e8  
6.666671664588418e8  
-2.014636993408203e-5

---

<div class="post-metadata">

**Author:** ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)\
**Post date:** [January 25, 2023, 7:32pm UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/2 "2023-01-25T19:32:04Z")

</div>

Relative difference of 1e-13 doesn’t look terribly bad, and yes, it’s expected.

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [January 26, 2023, 12:32am UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/3 "2023-01-26T00:32:13Z")

</div>

To expand on this a little bit: Floating point addition is not associative (`(a + b) + c` may return something different than `a + (b + c)`). Since `@turbo` is allowed to reorder the loop operations, you may therefore get slightly different results.

NB: Reading from and writing to non-constant global variables in a hot loop is never a good idea if you care about performance, so avoiding this first should give much larger performance improvements than just throwing `@turbo` on your loops.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 26, 2023, 1:25am UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/4 "2023-01-26T01:25:45Z")

</div>

`@turbo` will at least add a function barrier, so that it should be fast, even at global scope.  
That is, you should only pay the cost of a few dynamic dispatches for the code it generates outside the barrier, which is O(1) w/ respect to the number of loop iterations.

FWIW, it should be the more accurate of the two in this example on average.  
Try comparing with `BigFloat` and see which was closer.

---

<div class="post-metadata">

**Author:** ![pitsianis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pitsianis/32/26588_2.png) [@pitsianis](https://discourse.julialang.org/u/pitsianis)\
**Post date:** [January 26, 2023, 3:04pm UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/5 "2023-01-26T15:04:25Z")

</div>

To complement @simeonschaub’s answer, a simple demo like this clarifies the issue of non-associativity of floating point addition.

```julia
julia-1.8.5|v1.8> x = rand(10000); sum(x[end:-1:1]) - sum(x)
0.0

julia-1.8.5|v1.8> x = rand(10000); sum(x[end:-1:1]) - sum(x)
0.0

julia-1.8.5|v1.8> x = rand(10000); sum(x[end:-1:1]) - sum(x)
9.094947017729282e-13

```

The most accurate answer will be computed if you add together numbers with similar magnitudes.

---

<div class="post-metadata">

**Author:** ![Shashank](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shashank/32/12323_2.png) [@Shashank](https://discourse.julialang.org/u/Shashank)\
**Post date:** [January 26, 2023, 3:18pm UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/6 "2023-01-26T15:18:05Z")

</div>

Thanks a lot. I was not sure it was due to the floating point error. My concern was that using @turbo macro in my code could lead to a large error in certain circumstances. But now that I know it is due to the floating point error, I am not that worried.

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [January 28, 2023, 10:37am UTC](https://discourse.julialang.org/t/turbo-macro-giving-slightly-different-results/93529/7 "2023-01-28T10:37:03Z")

</div>

> [@Shashank](#):
>
> ```julia
> using LoopVectorization
> global ans1 = 0.0e0
> @turbo for i = 1:1000000
> ans1=ans1+sqrt(i)
> end
> println(ans1)
>     
> global ans2=0.0e0
> 
> for i = 1:1000000
> global ans2
> ans2=ans2+sqrt(i)
> end
> 
> ```

```julia
julia> using LoopVectorization

julia> global ans1 = 0.0e0
0.0

julia> @turbo for i = 1:1000000
           ans1=ans1+sqrt(i)
       end

julia> println(ans1)
6.666671664588217e8

julia> global ans2=0.0e0
0.0

julia> for i = 1:1000000
           global ans2
           ans2=ans2+sqrt(i)
       end

julia> ans3 = sum(sqrt∘big, 1:1000000) |> Float64;

julia> println(ans1-ans3)
-4.76837158203125e-7

julia> println(ans2-ans3)
1.9669532775878906e-5

julia> (ans2-ans3) / (ans1-ans3)
-41.25

```

For this particular example on my particular hardware (tiger lake CPU), the in-order sum has 40 times the error as the `@turbo` version.
