# Optimising switching algorithms based on value of struct field

**URL:** <https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404>\
**Category:** General Usage\
**Tags:** performance, struct, type-stability\
**Created:** [July 18, 2022, 12:58pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404 "2022-07-18T12:58:29Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 12:58pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/1 "2022-07-18T12:58:29Z")

</div>

I’m working on a simulation in Julia, where the “centrepiece” is some struct, which can have a few boolean properties associated with it.

```julia
mutable struct Sim
   """ data """
   
   prop_a::Bool
   prop_b::Bool
   ...

end

```

In the simulation I call a function to get the some energy dependent on this struct ten-thousands to millions of times, let’s call this function `getE(s::Sim)`. Any of the properties being false, means that I don’t want to include some term in this energy function, and thus can speed up this function by not checking a few of the data fields in the struct (which would otherwise be accessing the fields to add zeros to some float in the end).

Thus, in other words the implementation of `getE` depends on the properties of `s`. I can some if statements and only access the fields the corresponding properties are true. This is quite fast, but there still is a small performance hit, especially if I need to do multiple checks.

I thought it might be faster to just write all the functions beforehand and save one of them in the Sim struct itself. Thus

```julia
mutable struct Sim
   """ data """
   
   prop_a::Bool
   prop_b::Bool
   ...

   efunc::Function

end

```

When I change one of the props, which doesn’t happen often, I just change the function being referenced in the struct, so that no checks have to be done at runtime. Sadly, the performance hit by accessing the referenced function turns out to be orders of magnitude higher than checking the properties every time.

```julia
julia> @btime getE(s)
  13.556 ns (0 allocations: 0 bytes)

julia> @btime getECheckProp(s)
  14.404 ns (0 allocations: 0 bytes)

julia> @btime s.efunc(s)
  53.287 ns (1 allocation: 16 bytes)

```

Here `getE(s)` is the base algorithm, `getECheckProp(s)` checks the corresponding properties before calling `getE(s)`, and `s.efunc` is just a reference to `getE` directly.

Any suggestions of how I could build my program to get as close to the performance of calling `getE(s)` directly?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 18, 2022, 2:03pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/2 "2022-07-18T14:03:07Z")

</div>

Probably you just need to parametrize your structure to the type of function:

```julia
mutable struct Sim{F<:Function}
    ...
    efunc::F
end

```

otherwise `efunc` is abstractly typed. (consider making the structure immutable as well, that may help the compiler to do optimizations).

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 2:25pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/3 "2022-07-18T14:25:57Z")

</div>

Yep, you’re completely right. Now I can just redefine the method to any of the predefined methods, instead of the function itself. This works, thanks!

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 3:05pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/4 "2022-07-18T15:05:12Z")

</div>

Actually, there is one sidenote:

Say I have predefined `getE1(g), getE2(g) ...`. I need to programatically change `s.efunc` when I change one of the props. Naively I would do something like this:

```julia
function setPropB(s)
  s.prop_b = true
  s.efunc(s) = getE2(s)
end

```

this immediately gives the error

` ERROR: syntax: Global method definition around ... needs to be placed at the top level, or use "eval".`

Instead trying

```julia
function setPropB(s)
  s.prop_b = true
  eval(:(s.efunc(s) = begin; getE2(s); end ))
end

```

works, but is MetaProgramming, if I’m not mistaken, which is often discouraged here. Are there any caveats to using eval in this way?

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [July 18, 2022, 3:14pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/5 "2022-07-18T15:14:07Z")

</div>

Maybe you want

> [@f.ij](#):
>
> `s.efunc = getE2`

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 3:18pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/6 "2022-07-18T15:18:11Z")

</div>

That doesn’t work if you define efunc to be type stable like Imiq suggested

```julia
mutable struct Sim{F<:Function}
    ...
    efunc::F
end

```

And actually the whole point of my original post was, that that makes calling efunc very slow.

---

<div class="post-metadata">

**Author:** ![Jeff\_Emanuel](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeff_emanuel/32/15440_2.png) [@Jeff\_Emanuel](https://discourse.julialang.org/u/Jeff_Emanuel)\
**Post date:** [July 18, 2022, 3:22pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/7 "2022-07-18T15:22:19Z")

</div>

Sorry, I didn’t read the history. In that case you won’t be able to reassign efunc. Each function has its own type. Maybe you can have two function fields and a boolean field to indicate which function to use. It would be type stable, but you would need to check the boolean on each invocation which would slow it down, but maybe not as much as type instability.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 3:26pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/8 "2022-07-18T15:26:14Z")

</div>

Yes indeed that would indeed be faster than type instability in the function, but still gives a performance hit that I would like to overcome. Doing what Imiq suggested together with the eval trick does solve the speed problem though.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 18, 2022, 3:29pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/9 "2022-07-18T15:29:17Z")

</div>

Indeed, the whole point is to keep `efunc` constant, so that the compiler can optimize the code for it.

You probably want to define what `Sim` is only once (make it immutable, that will makes things clear and the overall program structure will probably get better, even if at first sight it looks more cumbersome).

You would, do, then:

```julia
struct Sim{F<:Function}
     param::Bool
     efunc::F
end

function setSim( some parameters )
       ...
    efunc(s) = whatever
    return Sim(param, efunc)
end

sim = setSim( ... )

# now on, use `sim` as a static structure.
```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 18, 2022, 3:33pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/10 "2022-07-18T15:33:53Z")

</div>

Maybe another alternative is to parametrize `Sim` not the function iself, but o the type of function. I think there are many packages which use this strategy. Something like:

```julia
struct Sim{T}
    param1::Bool
    param2::Bool
    # do not store the function here
end

struct FunctionType1 end
struct FunctionType2 end

# initialize sim:
sim = Sim{FunctionType1}(param1, param2)

# and define the functions to apply to sim, according to its type:

efunc(s::Sim{FunctionType1}) = something
efunc(s::Sim{FunctionType2}) = another something

```

By the way, if the possible `Sim`s have different types and number of parameters, then it is even better to just define different containing structs for each type of simulations, and dispatch on them:

```julia
struct SimType1
   p1::Bool
end

struct SimType2
    p1::Bool
    p2::Float64
end

sim = SimType1(p1)

efunc(s::SimType1) = something
efunc(s::SimType2) = another something

```

ps: @f.ij forget the `eval` option, don’t go that route (answering to your post bellow).

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 3:37pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/11 "2022-07-18T15:37:07Z")

</div>

I think I found a caveat: for eval to work I think s needs to be defined globally. This causes some problems with inner constructors for example:

```julia
function getE(s)
  ...
                end
mutable struct Sim{F <: Function}
  ...
  
  efunc::F
  
  Sim(...,prop_a,...) = ( sim = new{typeof(getE)}(..., getE); 
    if prop_a
       eval(:(s.efunc(s) = begin; getE1(s); end));
    else
       eval(:(s.efunc(s) = begin; getE2(s); end))
    end
    return sim )

s = Sim(...,true,...)

ERROR: LoadError: UndefVarError: s not defined

```

Adding the prefix global in front of sim within the inner constructor fixes the problem and doesn’t actually create a globally defined variable named sim, but feels wrong

```julia
mutable struct Sim{F <: Function}
  ...
  
  efunc::F
  
  Sim(...,prop_a,...) = ( global sim = new{typeof(getE)}(..., getE); 
    if prop_a
       eval(:(s.efunc(s) = begin; getE1(s); end));
    else
       eval(:(s.efunc(s) = begin; getE2(s); end))
    end
    return sim )

s = Sim(...,true,...)

```

Moreover, to change the function, what I did before:

```julia
function setPropB(s)
  s.prop_b = true
  eval(:(s.efunc(s) = begin; getE2(s); end ))
end

```

only works if `s` is in the global namespace, the function argument doesn’t actually matter for the eval function. I would now need to resort to macros and:

```julia
macro name(arg)
           string(arg)
end

function setPropB(s)
  simname = @name s
  s.prop_b = true
  eval( Meta.parse("$simname.efunc(s) = getE2(s)") )
end

```

but again, uses meta programming which is discouraged.

---

<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:** [July 18, 2022, 3:50pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/12 "2022-07-18T15:50:43Z")

</div>

I would not try to use dispatch for something that is inherently dynamic (the bool parameter values.)

Just use a regular branch, they are much faster than dynamic dispatch. Just run your test and branch, an possibly store the result of your test in a separate field on object creation.

Then

```julia
getE(s::Sim) = s.test_result ? branch1(s) : branch2(s) 

```

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 18, 2022, 3:54pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/13 "2022-07-18T15:54:28Z")

</div>

I do have to change the data fields of Sim quite often though (though most often it’s writing to arrays so that’s not a problem). Allocating a new struct when I change a parameter doesn’t seem great. Moreover, then I have the problem that I now have to have a type unstable global variable `sim`, which doesn’t seem great for performance either, since I call a lot of functions on `sim`, right?

I did actually try the eval option, and while not very elegant and using meta programming, it does achieve what I wanted, with no performance hit of using any of the functions.

---

<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:** [July 18, 2022, 3:58pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/14 "2022-07-18T15:58:29Z")

</div>

Storing the function in the struct is a bad idea, imho. Even if you parameterize the struct on the function type, it is inherently type-unstable, since the parameter depends on your bool parameters.

Using a branch is better, imho.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [July 18, 2022, 4:02pm UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/15 "2022-07-18T16:02:45Z")

</div>

> [@f.ij](#):
>
> I now have to have a type unstable global variable `sim`, which doesn’t seem great for performance either, since I call a lot of functions on `sim`, right?

Hard to say without a more general view of your code. But, in my imagination, you would be passing the `sim` object as a parameter to the functions that do the job, so you won’t have ever a global parameter.

```julia
sim = SimType1(p1)

result = simulation(sim)

etc...

```

with that, `simulation` will specialize to `sim` of type `SimType1`. if you have inside that a call to `getE(s) = ...` and you have previously defined `getE(s::SimType1) = something`, your code won’t have any branch, any dinamic dispatch, etc, the whole thing will just be compiled to the specialized type of `sim` you are defining from start.

ps: What I’m imagining you want to achieve is something with the following type of functionality:

```julia
sim = SimGravitational(params...)

# or

sim = SimMolecular(params...)

result = simulation(sim)

```

in which case you would have very different definitions of the energy and forces functions, like:

```julia
energy(s::SimGravitational) = gravitational energy

energy(s::SimMolecular) = molecular energy

etc.

```

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 21, 2022, 8:13am UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/16 "2022-07-21T08:13:17Z")

</div>

I don’t exactly see how parameter dependence causes type instability. The parameters are not checked by the function in this way, since I make sure that the correct function is stored when changing one of the parameters (which function is correct depends on the combination of parameters).

Branching might be an option though. I’m building a multi-threaded, interactive simulation. The simulation update itself is continuously run on a thread in a while true loop, basically. I could make the while loop be dependent on a global variable, so that other threads close the thread and open a new branched one when changing one of the parameters. Does anyone know how much overhead this would cause? I.e. `while true` vs `while var == true`.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 21, 2022, 8:44am UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/17 "2022-07-21T08:44:30Z")

</div>

I see, I think I didn’t do a good enough job explaining what I’m trying to do. Basically I’m building an interactive (multi-threaded) Monte Carlo simulation based on Ising-like models. What you’re saying I’ve already implemented, but wasn’t necessarily what I was looking for in this case (e.g. I have different structs for different type of ising models, and these are indeed just initialised once when the simulation is started). However, for a single model, I still might want to change these parameters and optimise the energy function.

As an example, I might want to add a magnetic field that’s not always on. The magnetic field being on would add an external value for each site in a lattice which has to be taken into account when updating. If the field is off, however, I don’t wan’t to access the magnetic field at all, as this slows down the calculation of the energy considerably. Thus, I want a way to be able to turn this magnetic field on and off mid simulation, and get the optimal speed in either case. Of course, when the field is on calculations will be a bit slower, but that’s unavoidable. What does seem avoidable is the overhead when the magnetic field is off. I might try the branching option though. This way I only need to check ever wether my main Monte Carlo thread should be running, and just close and reopen it if I change the parameters.

---

<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:** [July 21, 2022, 9:30am UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/18 "2022-07-21T09:30:54Z")

</div>

> [@f.ij](#):
>
> (which function is correct depends on the combination of parameters).

And that’s the type instability. The compiler cannot know beforehand which function/parameter is the correct one, because it depends on runtime values, and is not known statically.

Perhaps it’s not so bad, type instabilities can be acceptable, especially if it doesn’t occur in a hot loop.

---

<div class="post-metadata">

**Author:** ![f.ij](https://avatars.discourse-cdn.com/v4/letter/f/8491ac/32.png) [@f.ij](https://discourse.julialang.org/u/f.ij)\
**Post date:** [July 21, 2022, 9:42am UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/19 "2022-07-21T09:42:23Z")

</div>

But the types of the parameters are stable, just not the values.  
Or do you mean the type of the function? In that case that’s why I thought before that changing the method, not the function itself, might be a good solution, like Imiq suggested. However, then you run into the problems I mentioned in an earlier post.

---

<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:** [July 21, 2022, 9:46am UTC](https://discourse.julialang.org/t/optimising-switching-algorithms-based-on-value-of-struct-field/84404/20 "2022-07-21T09:46:23Z")

</div>

> [@f.ij](#):
>
> Or do you mean the type of the function?

Yes. But, perhaps that’s acceptable.
