# Function that executes two functions slower than two function separately

**URL:** <https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067>\
**Category:** New to Julia\
**Tags:** optimization\
**Created:** [July 25, 2023, 9:56am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067 "2023-07-25T09:56:45Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 25, 2023, 9:56am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/1 "2023-07-25T09:56:45Z")

</div>

So I have three types I defined as `Dist`, `Kernel` and `State`. I am running a function g defines as follows:

```julia
function g(x::Kernel, s::State)
    d = get_dist(x, s)
    return sample(d)

```

Where `d` is a `Dist` and `g` returns a `State`.

Now if I have a function f that does g sequentially twice for different kernels:

```julia
function f(x::Kernel, y::Kernel, s::State)
    s = g(x, s)
    s = g(y, s)
end

```

It runs about 3ms slower. For reference, `g(x, s)` takes about 7-8ms, `g(y, s)` takes less than 2ms. While `f` runs at about 13ms. Is there anyway to optimize further? What is the exact cause of this discrepancy?

`State` has two named tuples as fields while `Kernel` is an abstract type with singleton subtypes. I tried to not redefine the variable `s` in the function `f`. Weirdly enough that version of the function consumed less memory (I expected it to consume more since I’m defining two new states basically) but took longer to run.

---

<div class="post-metadata">

**Author:** ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)\
**Post date:** [July 25, 2023, 10:20am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/2 "2023-07-25T10:20:32Z")

</div>

Was the function `g` called before in your Julia session?

If you alter your function in the following way,

```julia
function f(x::Kernel, y::Kernel, s::State)
    @time "first g call" s = g(x, s)
    @time "second g call" s = g(y, s)
end

```

I think you’ll notice that the first `g` call also has some compilation time reported.

I suggest trying this as a test:

```julia
# do a `g` call here
@time "compiling g" g(x,y)

function f(x::Kernel, y::Kernel, s::State)
    @time "first g call" s = g(x, s)
    @time "second g call" s = g(y, s)
end

```

Now, when you call `f`, you should see similar time execution for the two `g` calls.

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 25, 2023, 10:52am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/3 "2023-07-25T10:52:02Z")

</div>

Sorry I guess my question wasn’t clear at all that’s my bad. The first `g` call and second `g` call are actually different functions because `x` and `y` are different concrete types. I would expect the first call to take more time so it’s not a compilation issue.

My problem is that the sum of the time taken by the two `g` functions by themselves is less than the time taken by `f` by an amount that’s significant for my purposes.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [July 25, 2023, 2:10pm UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/4 "2023-07-25T14:10:31Z")

</div>

Can you provide a full minimal working example? And how are you measuring the execution times?

Also, are the two different methods of `g` type stable? So can the output of the first line in the function `f` be inferred from the input types? (what does `@code_warntype f(x, y, s)` output?)

I don’t think some dynamic dispatch would account for more than a µs runtime cost, but it would be good to know anyway.

---

<div class="post-metadata">

**Author:** ![algunion](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/algunion/32/51630_2.png) [@algunion](https://discourse.julialang.org/u/algunion)\
**Post date:** [July 25, 2023, 2:36pm UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/5 "2023-07-25T14:36:05Z")

</div>

In fact, it was my bad: after closer reading, I see that this is a _sum larger than the sum of the parts_ issue.

Please check @Sevi’s post. That is the way 🙂

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 26, 2023, 9:45am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/6 "2023-07-26T09:45:07Z")

</div>

A minimal working example might be too complicated to do. But I was measuring execution times using `@benchmark` (i.e. `@benchmark f($x, $y, $s)`). `@code_warntype` gives me all blue so I think I’m good with that regard.

I think I have an idea of what is going on though. Calling `g(y, s)` changes parts of `s` that `g(x, s)` depends on but wouldn’t change itself. So I’m guessing there might be some optimization that happens when just running `g(x, s)`. Just a guess though.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [July 26, 2023, 10:08am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/7 "2023-07-26T10:08:34Z")

</div>

That does indeed sound strange…

When you benchmark the individual runs of `g`, are you using the same `s`?

---

<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:** [July 26, 2023, 11:47am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/8 "2023-07-26T11:47:35Z")

</div>

Full problem too big for cache, but subproblems fit?

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 27, 2023, 10:10am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/9 "2023-07-27T10:10:19Z")

</div>

Yes, I was using the same `s`. Whereas in `f` the `s` would randomly change after the first call for `g`.

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 27, 2023, 10:13am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/10 "2023-07-27T10:13:31Z")

</div>

Is there any way to check this? `s` is about 18 MB in memory.

---

<div class="post-metadata">

**Author:** ![Sevi](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Sevi](https://discourse.julialang.org/u/Sevi)\
**Post date:** [July 27, 2023, 10:15am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/11 "2023-07-27T10:15:56Z")

</div>

Then this might be why the timings are different. Depending on how `s` is changed internally, the function just might need longer to execute.

If you benchmark exactly the same calls that happen inside `f`, i.e. using the modified `s` to benchmark the second call to `g`, do you still get different timings?

---

<div class="post-metadata">

**Author:** ![Jad\_Zeitouni](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jad_zeitouni/32/50678_2.png) [@Jad\_Zeitouni](https://discourse.julialang.org/u/Jad_Zeitouni)\
**Post date:** [July 27, 2023, 10:35am UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/12 "2023-07-27T10:35:02Z")

</div>

Actually never mind. Even when I use the same `s` in `f` without altering its value, I get the same run times, so I don’t think it has to do with any efficiency lost in `s` changing.

---

<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:** [July 27, 2023, 3:48pm UTC](https://discourse.julialang.org/t/function-that-executes-two-functions-slower-than-two-function-separately/102067/13 "2023-07-27T15:48:09Z")

</div>

> [@Jad\_Zeitouni](#):
>
> Is there any way to check this? `s` is about 18 MB in memory.

18 MB makes this seem likely. 18 MB is in the ballpark of typical L3 cache sizes.

You can try a smaller `s`.  
If you’re on Linux, you can use `LinuxPerf.jl` to see how the cache misses change between evaluating components separately, versus together.

You could try blocking your algorithm, if that’s at all possible.  
That is, break `s` into chunks that fit in cache, and operate on these chunks.
