# Boltzmann Factor in a loop

**URL:** <https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086>\
**Category:** Performance\
**Created:** [March 31, 2018, 2:08pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086 "2018-03-31T14:08:16Z")\
**Posts on this page:** 19\
**Page:** 2

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [April 1, 2018, 7:56pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/21 "2018-04-01T19:56:40Z")

</div>

… and types.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 1, 2018, 10:49pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/22 "2018-04-01T22:49:10Z")

</div>

Why - I thought that is not normally needed? My understanding here was that functions are a bit special because of this compiler optimisation? What am I missing?

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [April 2, 2018, 12:14am UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/23 "2018-04-02T00:14:53Z")

</div>

> <https://github.com/JuliaLang/julia/issues/23471>
>
> On 0.6.0,
> 
> \`\`\`julia
> foo1(t::Type, x) = Nullable{t}(sin(x))
> foo2(t…::Type{T}, x) where T = Nullable{t}(sin(x))
> 
> @btime foo1(Float64, 2)
> 408.815 ns (2 allocations: 48 bytes) # same with @allocated
> @btime foo2(Float64, 2)
> 17.359 ns (0 allocations: 0 bytes)
> \`\`\`
> 
> However, both functions are \`@inferred\` correctly, and have the same \`@code\_llvm\`. Why does \`foo1\` allocate?
> 
> Might be related to #19137

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 2, 2018, 12:17am UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/24 "2018-04-02T00:17:37Z")

</div>

I see - thank you!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 2, 2018, 7:52am UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/25 "2018-04-02T07:52:19Z")

</div>

I agree that it is a confusing right now. We typically say that function argument types is only used for dispatch and has no effect on performance. This is an exception to that.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 2, 2018, 11:29am UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/26 "2018-04-02T11:29:36Z")

</div>

It would be good to have clear documentation about this. I guess he issue linked above is about that?

---

<div class="post-metadata">

**Author:** ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)\
**Post date:** [April 3, 2018, 5:27pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/27 "2018-04-03T17:27:17Z")

</div>

I wanted to revisit this topic with a similar piece of code. The following is a minimal example associated with a stochastic sampling method that uses the gradient of the potential, V(x), in its computation. I tried using the `where` command, and obtained rather disappointing results:

```julia
function run0(x0, gradV::gradVf, niterations) where {gradVf}

    X0 = similar(x0);
    gradV0 = similar(x0);
    @. X0 = x0; # copy over initial condition

    for j = 1:niterations
        gradV0 .= gradV(X0);
    end
end

function gradV(x)
    gradV = 4 * (dot(x,x) -1 ) * x;
    return gradV
end

niterations = 10^6;

X0 = .5 * ones(2);

@time run0(X0, gradV, niterations);

```

After the second run, of this, I get:

```julia
julia> @time run0(X0, gradV, niterations);
  0.070732 seconds (1.00 M allocations: 91.553 MiB, 9.93% gc time)

```

And the memory usage linearly scales with the number of iterations. The only difference between this and the other example is that `gradV` is a \mathbb{R}^d\to \mathbb{R}^d function while `V` was a \mathbb{R}^d\to \mathbb{R} function.

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 3, 2018, 5:42pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/28 "2018-04-03T17:42:06Z")

</div>

But this is just because you are allocating a new vector inside the function in every iteration?

---

<div class="post-metadata">

**Author:** ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)\
**Post date:** [April 3, 2018, 5:49pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/29 "2018-04-03T17:49:08Z")

</div>

Shouldn’t preallocating the `gradV0` vector (`gradV0 = similar(x0);`) and then using the `.=` assignment operation avoid creating a new vector each time? If not, how would I code this to avoid the creation of a new vector at each iteration?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 3, 2018, 6:05pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/30 "2018-04-03T18:05:07Z")

</div>

`gradV(X0)` allocates a vector which is copied to `gradV0`. You can send in `gradV0` to the function and assign to it there.

---

<div class="post-metadata">

**Author:** ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)\
**Post date:** [April 3, 2018, 6:10pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/31 "2018-04-03T18:10:41Z")

</div>

So the C-style solution of passing a pointer to the array that is being populated with new values is the recommended approach for this scenario?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 3, 2018, 6:26pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/32 "2018-04-03T18:26:50Z")

</div>

Well, if you want to assign in place to a vector then you need to have a handle to that vector.

---

<div class="post-metadata">

**Author:** ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)\
**Post date:** [April 3, 2018, 6:40pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/33 "2018-04-03T18:40:05Z")

</div>

Consider this version of the problem:

```julia
using ForwardDiff
function run1(x0, V::Vf, niterations) where {Vf}

    X0 = similar(x0);
    gradV0 = similar(x0);
    @. X0 = x0; 

    for j = 1:niterations
        ForwardDiff.gradient!(gradV0, V, X0);
    end
end

function V(x)
    @fastmath V = (dot(x,x)-1)^2;
    return V
end

niterations = 10^4;

X0 = .5 * ones(2);

```

with

```julia
julia> @time run1(X0, V, niterations);
  0.059611 seconds (60.01 k allocations: 2.900 MiB, 8.54% gc time)

```

and when I increase the number of iterations:

```julia
julia> niterations = 10^6;

julia> @time run1(X0, V, niterations);
  5.537944 seconds (6.00 M allocations: 289.917 MiB, 0.43% gc time)

```

Though perhaps this is a problem with `ForwardDiff`.

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 3, 2018, 6:42pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/34 "2018-04-03T18:42:03Z")

</div>

Maybe try to write an in-place gradient `gradV!` that doesn’t allocate?

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 3, 2018, 6:42pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/35 "2018-04-03T18:42:56Z")

</div>

Or use StaticArrays

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 3, 2018, 6:49pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/36 "2018-04-03T18:49:09Z")

</div>

[http://www.juliadiff.org/ForwardDiff.jl/stable/user/api.html#Preallocating/Configuring-Work-Buffers-1](http://www.juliadiff.org/ForwardDiff.jl/stable/user/api.html#Preallocating/Configuring-Work-Buffers-1)

---

<div class="post-metadata">

**Author:** ![cortner](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cortner/32/204_2.png) [@cortner](https://discourse.julialang.org/u/cortner)\
**Post date:** [April 3, 2018, 6:51pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/37 "2018-04-03T18:51:43Z")

</div>

was about to send the same link 🙂

---

<div class="post-metadata">

**Author:** ![gideonsimpson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gideonsimpson/32/1928_2.png) [@gideonsimpson](https://discourse.julialang.org/u/gideonsimpson)\
**Post date:** [April 3, 2018, 6:58pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/38 "2018-04-03T18:58:57Z")

</div>

That doesn’t really seem to improve things. With

```julia
function run1(x0, V::Vf, niterations) where {Vf}

    X0 = similar(x0);
    gradV0 = similar(x0);
    @. X0 = x0;

    gradcfg = ForwardDiff.GradientConfig(V, X0);

    for j = 1:niterations
        ForwardDiff.gradient!(gradV0, V, X0,gradcfg);
    end
end

function V(x)
    @fastmath V = (dot(x,x)-1)^2;
    return V
end

niterations = 10^6;

X0 = .5 * ones(2);

```

I get:

```julia
julia> @time run1(X0, V, niterations);
  0.477692 seconds (4.00 M allocations: 122.071 MiB, 1.46% gc time)

```

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [April 3, 2018, 9:30pm UTC](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086/39 "2018-04-03T21:30:22Z")

</div>

Removing the `@slowmath` macro makes the allocations go down to 1 per iteration.

To improve the run time slightly we can either create the `GradientConfig` with an explicit chunk size like:

```julia
gradcfg = ForwardDiff.GradientConfig(V, X0, ForwardDiff.Chunk{2}())

```

or put the creation of the config behind a function-barrier.

```julia
julia> @time run1(X0, V, niterations);
  0.300106 seconds (1.00 M allocations: 30.518 MiB, 0.93% gc time)

```

I’m not sure where the last allocation in each iteration comes from.

Using a StaticArray which doesn’t need any preallocation or configs:

```julia
julia> @time run1(rand(SVector{2}), V, niterations);
  0.008152 seconds (17 allocations: 928 bytes)

```

[Previous page](https://discourse.julialang.org/t/boltzmann-factor-in-a-loop/10086.md?page=1)
