# BigFloat performance, allocates like crazy!

**URL:** <https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892>\
**Category:** General Usage\
**Created:** [February 7, 2018, 12:00pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892 "2018-02-07T12:00:45Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 12:00pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/1 "2018-02-07T12:00:45Z")

</div>

I have a program which allocates less than 35 MB and takes under 2 seconds with Float64 and Float32, but allocates 350 GB and takes more than 10 minutes with BigFloat, is this expected? The code is seemingly type stable. Are there other recommendations for high precision calculations without all the allocations, perhaps not as big as the 256 bits of BigFloat but still more than 64 bits? I would appreciate your comments.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 12:15pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/2 "2018-02-07T12:15:58Z")

</div>

I think DoubleDouble is what I am looking for:

```julia
julia> using DoubleDouble

julia> using BenchmarkTools

julia> a = Double{Float64}(1); b = Double{Float64}(2);

julia> @btime a + b
  20.421 ns (1 allocation: 32 bytes)
Double(3.0, 0.0)
 - value: 3

julia> a = Float64(1); b = Float64(2);

julia> @btime a + b
  17.868 ns (1 allocation: 16 bytes)
3.0

julia> a = BigFloat(1); b = BigFloat(2);

julia> @btime a + b
  91.168 ns (2 allocations: 88 bytes)
3.000000000000000000000000000000000000000000000000000000000000000000000000000000

julia> a = Double{Float64}(1); b = Double{Float64}(2);

julia> @btime a * b
  32.091 ns (1 allocation: 32 bytes)
Double(2.0, 0.0)
 - value: 2

julia> a = Float64(1); b = Float64(2);

julia> @btime a * b
  19.327 ns (1 allocation: 16 bytes)
2.0

julia> a = BigFloat(1); b = BigFloat(2);

julia> @btime a * b
  111.090 ns (2 allocations: 88 bytes)
2.000000000000000000000000000000000000000000000000000000000000000000000000000000

julia> a = Double{Float64}(1); b = Double{Float64}(2);

julia> @btime a / b
  38.482 ns (1 allocation: 32 bytes)
Double(0.5, 0.0)
 - value: 0.5

julia> a = Float64(1); b = Float64(2);

julia> @btime a / b
  19.692 ns (1 allocation: 16 bytes)
0.5

julia> a = BigFloat(1); b = BigFloat(2);

julia> @btime a / b
  195.918 ns (2 allocations: 88 bytes)
5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01

```

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 12:18pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/3 "2018-02-07T12:18:22Z")

</div>

Also [GitHub - saschatimme/HigherPrecision.jl: High precision replacements for Float64](https://github.com/saschatimme/HigherPrecision.jl), should have probably done a better search 😄

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [February 7, 2018, 3:01pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/4 "2018-02-07T15:01:50Z")

</div>

MPFR Bigfloats are actually mutable because, since they are arbitrary precision, they are implemented on an array. Working with them with full mutability is kind of crazy though from what I understand, so they are exposed in Julia like any other number: immutable. But this does mean allocating a lot, and there’s no good solution for now except for using a smaller fixed precision number.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [February 7, 2018, 3:17pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/5 "2018-02-07T15:17:10Z")

</div>

Your timings are actually dramatically off, because you’re not interpolating the variables:

```julia
a, b = 2.0, 3.0
A, B = BigFloat(a), BigFloat(b)
aa, bb = Double(a), Double(b)

julia> @btime $a + $b
  1.456 ns (0 allocations: 0 bytes)
5.0

julia> @btime $A + $B
  95.115 ns (2 allocations: 104 bytes)
5.000000000000000000000000000000000000000000000000000000000000000000000000000000

julia> @btime $aa + $bb
  4.615 ns (0 allocations: 0 bytes)
Double(5.0, 0.0)
 - value: 5

```

As you can see, the difference is much more dramatic than your benchmarks indicated. It should, however, raise a big red flag when scalar float addition allocates and takes 20ns!

Takeaway lesson: interpolate non-constant variables!

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 8:22pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/6 "2018-02-07T20:22:16Z")

</div>

> [@DNF](#):
>
> Takeaway lesson: interpolate non-constant variables!

Of course, thanks for pointing that out, I always to forget to do that! New benchmarks:

```julia
julia> using HigherPrecision

julia> using BenchmarkTools

julia> a = Float32(1); b = Float32(2);

julia> A = BigFloat(1); B = BigFloat(2);

julia> aa = DoubleFloat64(1); bb = DoubleFloat64(2);

julia> @btime $a + $b
  1.093 ns (0 allocations: 0 bytes)
3.0f0

julia> @btime $A + $B
  70.460 ns (2 allocations: 88 bytes)
3.000000000000000000000000000000000000000000000000000000000000000000000000000000

julia> @btime $aa + $bb
  6.564 ns (0 allocations: 0 bytes)
3

julia> @btime $a * $b
  1.093 ns (0 allocations: 0 bytes)
2.0f0

julia> @btime $A * $B
  88.870 ns (2 allocations: 88 bytes)
2.000000000000000000000000000000000000000000000000000000000000000000000000000000

julia> @btime $aa * $bb
  1.823 ns (0 allocations: 0 bytes)
2

julia> @btime $a / $b
  1.093 ns (0 allocations: 0 bytes)
0.5f0

julia> @btime $A / $B
  169.787 ns (2 allocations: 88 bytes)
5.000000000000000000000000000000000000000000000000000000000000000000000000000000e-01

julia> @btime $aa / $bb
  7.658 ns (0 allocations: 0 bytes)
0.5

```

DoubleDouble doesn’t currently support some operations I am using like ^ but HigherPrecision looks incredible! I think the 60-150 times slowdown in scalar arithmetic compared to Float32 could explain the time difference I am observing, there is probably also some SIMD and caching magic for the Float32 going on behind the scenes in my real program. But HigherPrecision promises at least a 10 times speedup from BigFloat so looking forward to trying that after ironing a few things out.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [February 7, 2018, 8:32pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/7 "2018-02-07T20:32:16Z")

</div>

> [@mohamed82008](#):
>
> there is probably also some SIMD and caching magic for the Float32 going on behind the scenes in my real program.

No, SIMD only applies to multiple operations that are done together. There’s no possible SIMD here. That difference is likely because the multi-precision type has to do 2-4 operations on 64-bit floats. Basically, they get higher precision by having two pieces, and smartly doing an extra operation or two to catch the overflowing error of the 1st set of numbers into the second set. The reason this is done is because quad precision isn’t actually supported on the die, so this is an implementation which just uses normal floating point registers instead of software emulation which would be slow.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 8:34pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/8 "2018-02-07T20:34:41Z")

</div>

> [@ChrisRackauckas](#):
>
> No, SIMD only applies to multiple operations that are done together.

Yes I have a bunch of array operations and simd-able loops in the actual code which I believe the compiler maybe vectorizing for me. And a cache line and a register would hold more `Float32`s than `DoubleFloat64`s so that’s another source of speed difference.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [February 7, 2018, 8:36pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/9 "2018-02-07T20:36:41Z")

</div>

> [@mohamed82008](#):
>
> Yes I have a bunch of array operations and simd-able loops in the actual code which I believe the compiler maybe vectorizing for me.

Okay then yes, that would probably add a difference that the microbenchmarks don’t show.

---

<div class="post-metadata">

**Author:** ![mohamed82008](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mohamed82008/32/18171_2.png) [@mohamed82008](https://discourse.julialang.org/u/mohamed82008)\
**Post date:** [February 7, 2018, 8:37pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/10 "2018-02-07T20:37:56Z")

</div>

Yup.

---

<div class="post-metadata">

**Author:** ![ScottPJones](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scottpjones/32/146_2.png) [@ScottPJones](https://discourse.julialang.org/u/ScottPJones)\
**Post date:** [February 7, 2018, 10:50pm UTC](https://discourse.julialang.org/t/bigfloat-performance-allocates-like-crazy/8892/11 "2018-02-07T22:50:43Z")

</div>

Another one to try would be Dec128
