# Exponentiation of floats

**URL:** https://discourse.julialang.org/t/exponentiation-of-floats/105951
**Category:** Performance
**Tags:** question
**Created:** [November 8, 2023, 2:18pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951 "2023-11-08T14:18:26Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![richard\_sti](https://avatars.discourse-cdn.com/v4/letter/r/dec6dc/32.png) [@richard\_sti](https://discourse.julialang.org/u/richard_sti)
#### Post date: [November 8, 2023, 2:18pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/1 "2023-11-08T14:18:26Z")

</div>

Hi, I noticed that there is a significant loss of performance between Julia 1.7.3 and 1.9.x for exponentiation of floats, which becomes ~ 5 times slower. I tested this independently on a few machines. A minimal example of this is attached below.

```julia
using BenchmarkTools

function test()
    x = 1.
    for i in 1:100_000_000
        x += x^2.
    end
    return x
end

@btime test()

```

The problem remains in the available version of Julia 1.10.x, which is in fact 2 times slower than 1.9.x.

Thanks!

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [November 8, 2023, 2:30pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/2 "2023-11-08T14:30:23Z")

</div>

This is aside from the regression, but do you really need to exponentiate _by_ a float? I see 6x faster performance with `x += x^2` (without the `.`).

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [November 8, 2023, 2:36pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/3 "2023-11-08T14:36:11Z")

</div>

> [@mbauman](#):
>
> but do you really need to exponentiate _by_ a float?

idk if OP needs it but some fields need it:  
[https://cds.cern.ch/record/2866130/files/ANA-EXOT-2022-18-PAPER.pdf#page=9](https://cds.cern.ch/record/2866130/files/ANA-EXOT-2022-18-PAPER.pdf#page=9)

---

<div class="post-metadata">

### Author: ![richard\_sti](https://avatars.discourse-cdn.com/v4/letter/r/dec6dc/32.png) [@richard\_sti](https://discourse.julialang.org/u/richard_sti)
#### Post date: [November 8, 2023, 2:38pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/4 "2023-11-08T14:38:26Z")

</div>

Yes, I am aware that if one uses an integer it is much faster. However, I do require exponentiating by floats in general and this is a very significant difference between older and newer version of Julia.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [November 8, 2023, 2:41pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/5 "2023-11-08T14:41:04Z")

</div>

how fast was the older version? I have opened an issue: [Exponential by a float is very slow · Issue #52079 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/52079)

---

<div class="post-metadata">

### Author: ![richard\_sti](https://avatars.discourse-cdn.com/v4/letter/r/dec6dc/32.png) [@richard\_sti](https://discourse.julialang.org/u/richard_sti)
#### Post date: [November 8, 2023, 2:42pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/6 "2023-11-08T14:42:51Z")

</div>

That minimal example on 1.7.3 is ~ 220 ms whereas on 1.9.3 it is ~ 900 ms and on 1.10.x 2100 ms.

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [November 8, 2023, 2:44pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/7 "2023-11-08T14:44:38Z")

</div>

for me it’s same speed on 1.7:

```julia
julia> @benchmark x^y setup=begin x=rand(); y=rand()end
BenchmarkTools.Trial: 10000 samples with 989 evaluations.
 Range (min … max): 46.524 ns … 126.397 ns ┊ GC (min … max): 0.00% … 0.00%
 Time (median): 51.524 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 54.200 ns ± 8.123 ns ┊ GC (mean ± σ): 0.00% ± 0.00%

  █ ▁▅ ▄▇ ▂▄ ▂
  █▃▁▇██▇█▇▇▇█████▆▅▅▆▃▄▄▁▅▁▄▃▃▄▃▄▃▁▁▃▃▁██▆▄▅▇▇▇▇▇▇▇▇▆▅▇▇██▆▆▇ █
  46.5 ns Histogram: log(frequency) by time 69.4 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

```

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 2:46pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/8 "2023-11-08T14:46:58Z")

</div>

For what it’s worth in this example, the `2.` is getting converted to `2` inside the power function.

> <https://github.com/JuliaLang/julia/blob/bc55f44e17e9d1d72c9c9a87a1a60cf4bb5a17ad/base/math.jl#L1120>

In the llvm IR of `test` on 1.9.3, same thing occurs on 1.10-rc1

```llvm
%1 = call double @j_pow_body_301(double %value_phi1, i64 signext 2) #0

```

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 2:50pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/9 "2023-11-08T14:50:18Z")

</div>

I see a 2x regression from 1.9.3 to 1.10-rc1. The `@noinline x^yint` doesn’t inline/ const prop as well as it does on 1.9.3 which could be the problem.

EDIT: Manually bypassed the call in 1.10 to `^` and inserted a `pow_body` call to match 1.9.3 but didn’t make a difference. Likely the regression is in `pow_body` as otherwise the LLVM IR seems to be identical.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 3:07pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/10 "2023-11-08T15:07:01Z")

</div>

Do you happen to be running this on a fairly old CPU? For cpus with FMA (haswell/bulldozer or newer) floating point powers should have gotten a lot faster.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 3:09pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/11 "2023-11-08T15:09:41Z")

</div>

Note that this is a pretty bad benchmark since `1^x` is a special case so you are bench-marking the speed of a specific case rather than floating point exponentiation in general.

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 3:11pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/12 "2023-11-08T15:11:14Z")

</div>

I don’t think so,

```julia
julia> versioninfo()
Julia Version 1.9.3
Commit bed2cd540a (2023-08-24 14:43 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 16 × AMD Ryzen 7 5700U with Radeon Graphics
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-14.0.6 (ORCJIT, znver2)
  Threads: 1 on 16 virtual cores

```

I’m fairly confused though as far as I can tell there’s been no change to the code between 1.9.3 and 1.10-rc1 and the LLVM IR is near identical. Especially as `^2` is the same speed on both versions.

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 3:12pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/13 "2023-11-08T15:12:26Z")

</div>

The function is adding to `x` so it’s only `1^2.` on the first iteration.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 3:14pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/14 "2023-11-08T15:14:12Z")

</div>

Oh, right. It’s still a bad benchmark, but for a different reason After the first 12 iterations, it’s computing `Inf^2` which is also a special case.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 3:27pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/15 "2023-11-08T15:27:41Z")

</div>

You’re right that something is wrong with 1.10 (not sure what yet).  
A better version of this benchmark would be

```julia
function test()
    x = 1.1
    for i in 1:100_000_000
        x = x^2.0
        x > 1e160 && (x = 1.1)
    end
    return x
end

```

Which gives me ~740 ms on 1.9 and nightly, but 1.3s on 1.10. This is very odd since we didn’t change anything here between 1.10 and nightly as far as I know.

---

<div class="post-metadata">

### Author: ![richard\_sti](https://avatars.discourse-cdn.com/v4/letter/r/dec6dc/32.png) [@richard\_sti](https://discourse.julialang.org/u/richard_sti)
#### Post date: [November 8, 2023, 3:36pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/16 "2023-11-08T15:36:05Z")

</div>

Yep, this is a better example but the problem is still there. What speed do you get for 1.7.3? In my tests that one is still faster than 1.9.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 3:58pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/17 "2023-11-08T15:58:07Z")

</div>

I can confirm this. That said, this seems to be a regression purely for the case of raising a number to the `2.0` power. If I change the power to `2.1` I get 9.6 seconds on 1.7, vs 3 seconds on 1.9. Also for a power of `3.0` I get a time of 390ms for 1.7 vs 285 for 1.9

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 4:03pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/18 "2023-11-08T16:03:10Z")

</div>

I see a regression from 1.9 to 1.10 for `2.0`, `3.0` (197ms to 320ms) and `4.0` (817ms to 1.6s) and `4.1` (3.5s to 4.5s) for your example.

---

<div class="post-metadata">

### Author: ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)
#### Post date: [November 8, 2023, 4:03pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/19 "2023-11-08T16:03:49Z")

</div>

yeah. the 1.9 to 1.10 issue is real (and very weird)

---

<div class="post-metadata">

### Author: ![Zentrik](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zentrik/32/35409_2.png) [@Zentrik](https://discourse.julialang.org/u/Zentrik)
#### Post date: [November 8, 2023, 4:04pm UTC](https://discourse.julialang.org/t/exponentiation-of-floats/105951/20 "2023-11-08T16:04:25Z")

</div>

> <https://github.com/JuliaLang/julia/blob/5aaa94854367ca875375e38ae14f369f124e7315/base/math.jl#L54-L60>

My profile of 1.10-rc1 unlike in 1.9.3 seems to suggest that the non-fma path for `two_mul` is being called.

1.10-rc1

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/2/12aa326cdb6fd4882b6e575832915a6bba055124.png)

1.9.3

 ![image](https://global.discourse-cdn.com/julialang/original/3X/a/d/ad780aed6fb6f049983c00d5074179a7bf9952a5.png)

Weirdly LLVM IR says we’re using fma path

```llvm
julia> @code_llvm Base.Math.two_mul(1., 2.)
; @ math.jl:54 within `two_mul`
; Function Attrs: uwtable
define void @julia_two_mul_451([2 x double]* noalias nocapture noundef nonnull sret([2 x double]) align 8 dereferenceable(16) %0, double %1, double %2) #0 {
common.ret:
; @ math.jl:56 within `two_mul`
; ┌ @ float.jl:411 within `*`
   %3 = fmul double %1, %2
; └
; @ math.jl:57 within `two_mul`
; ┌ @ float.jl:407 within `-`
   %4 = fneg double %3
; └
; ┌ @ floatfuncs.jl:439 within `fma`
; │┌ @ floatfuncs.jl:434 within `fma_llvm`
    %5 = call double @llvm.fma.f64(double %1, double %2, double %4)
; └└
  %newstruct.sroa.0.0..sroa_idx = getelementptr inbounds [2 x double], [2 x double]* %0, i64 0, i64 0
  store double %3, double* %newstruct.sroa.0.0..sroa_idx, align 8
  %newstruct.sroa.2.0..sroa_idx8 = getelementptr inbounds [2 x double], [2 x
 double]* %0, i64 0, i64 1
  store double %5, double* %newstruct.sroa.2.0..sroa_idx8, align 8
; @ math.jl within `two_mul`
  ret void
}

```

[Next page](https://discourse.julialang.org/t/exponentiation-of-floats/105951.md?page=2)
