# Cores not optimally used

**URL:** <https://discourse.pymc.io/t/cores-not-optimally-used/16165>\
**Category:** version agnostic\
**Tags:** bug\
**Created:** [November 22, 2024, 10:58am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165 "2024-11-22T10:58:27Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 22, 2024, 10:58am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/1 "2024-11-22T10:58:27Z")

</div>

Hi  
I’m using PyMC with default option (i.e. 4 traces, no cores option) on a 4 core/8 thread machine.  
Instead of using all cores, it puts 2 chains on one core.

ps uax shows  
472689 xx 20 0 2285228 849228 19000 R 50.0 3.5 2:48.93 python  
472686 xx 20 0 2285196 849228 19000 R 49.7 3.5 2:48.73 python  
472687 xx 20 0 2285196 849228 19000 R 49.7 3.5 2:49.56 python  
472688 xx 20 0 2285196 849228 19000 R 49.7 3.5 2:49.31 python

By distributing over all cores, it should alllow a 2x speedup.

I also don’t see the typical core-switching that one usually sees with running CPU intense jobs.

Finally, also testing on a workstation with many cores. Same result.

---

<div class="post-metadata">

**Author:** ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)\
**Post date:** [November 22, 2024, 11:40am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/2 "2024-11-22T11:40:22Z")

</div>

I think by default pymc uses as many cores as chains? Did you try setting cores argument to pm.sample explictly?

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 22, 2024, 4:16pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/3 "2024-11-22T16:16:18Z")

</div>

Hi  
Setting cores in pm.sample(cores=4) did not change anything.

I think it is deeper down the rabbithole on how pymc deals with parallel jobs.

---

<div class="post-metadata">

**Author:** ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)\
**Post date:** [November 25, 2024, 10:17am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/4 "2024-11-25T10:17:12Z")

</div>

Setting cores=4, results in PyMC trying to still sample 2 chains x 2 cores only? Can you show the logging message it prints?

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 11:03am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/5 "2024-11-25T11:03:11Z")

</div>

It runs 4 chains alright, but they are distributed over 2 cores only, not 4.

What log do you like?

---

<div class="post-metadata">

**Author:** ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)\
**Post date:** [November 25, 2024, 5:25pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/6 "2024-11-25T17:25:41Z")

</div>

This line: [pymc/pymc/sampling/mcmc.py at 5352798ee0d36ed566e651466e54634b1b9a06c8 · pymc-devs/pymc · GitHub](https://github.com/pymc-devs/pymc/blob/5352798ee0d36ed566e651466e54634b1b9a06c8/pymc/sampling/mcmc.py#L859)

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 5:40pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/7 "2024-11-25T17:40:44Z")

</div>

It reports:  
Multiprocess sampling (4 chains in 4 jobs)

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 5:41pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/8 "2024-11-25T17:41:51Z")

</div>

What does PyMc use for multithreading?

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 5:48pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/9 "2024-11-25T17:48:24Z")

</div>

Tried OMP\_NUM\_THREADS=4 and OMP\_NUM\_THREADS=1, but saw no difference.  
Ipython vs python made no difference either.

---

<div class="post-metadata">

**Author:** ![aseyboldt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/aseyboldt/32/5795_2.png) [@aseyboldt](https://discourse.pymc.io/u/aseyboldt)\
**Post date:** [November 25, 2024, 8:01pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/10 "2024-11-25T20:01:34Z")

</div>

Can you show a complete example that we can run locally to compare?

This here uses 4 cores as it should on my machine with pymc 5.18.2:

```auto
import pymc as pm
import numpy as np
import pytensor.tensor as pt

with pm.Model() as model:
    pm.Normal("x", shape=1000)

with model:
    trace = pm.sample(draws=100_000, chains=4, cores=4, blas_cores="auto")

```

You can also try to change the blas\_cores argument. If your logp function spends a lot of time in blas calls (matrix multiplications etc), that might change the behaviour, although I don’t understand why it would only use half the cores by default. This also uses 4 cores locally for me:

```auto
import pymc as pm
import numpy as np
import pytensor.tensor as pt

A = np.random.randn(1000, 1000)

with pm.Model() as model:
    x = pm.Normal("x", shape=1000)
    b = pm.Normal("y", mu=A @ x, shape=1000)

with model:
    trace = pm.sample(draws=100_000, chains=4, cores=4, blas_cores="auto")

```

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 8:59pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/11 "2024-11-25T20:59:46Z")

</div>

Thanks for helping out.  
I tried the first script with also changing the blas\_cores, same result as before: only 2 cores used, 50% cpu per python process.  
This is with pyc 5.18.1

I start to suspect whatever library pymc is using, is misbehaving. Also because this odd core stickiness.  
Usually jobs move around when the cpu is not fully loaded to improve thermals. Here this doesn’t happen.

I regularly use Python’s multiprocessing library, and that works fine.  
I checked whether psutils returns the right number of cores, and it does.

---

<div class="post-metadata">

**Author:** ![aseyboldt](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/aseyboldt/32/5795_2.png) [@aseyboldt](https://discourse.pymc.io/u/aseyboldt)\
**Post date:** [November 25, 2024, 9:25pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/12 "2024-11-25T21:25:17Z")

</div>

That’s really strange. PyMC just uses multiprocessing, there is nothing particularly special happening.

Can you try to disable the progessbar? That also has some extra threads, and while I don’t see why it would cause something like that, better to disable it for debugging I think.

Can you also check if this is using the 4 threads correctly?

```python
import multiprocessing as mp

def run_loop():
    while True:
        pass

processes = [mp.Process(target=run_loop) for _ in range(4)]

for process in processes:
    process.start()

```

Other than that, what operating system are you using? How did you install the packages? Anything else that could be unusual about your setup?

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 25, 2024, 10:43pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/13 "2024-11-25T22:43:46Z")

</div>

The multiprocessing script uses all cores.  
Turning the progress bar off in the previous script made no difference.

The multiprocessing function call has a cores option too.  
E.g. pool = Pool(maxcpu=20)

Is this inherited from pymc?

For the rest, this is Ubuntu with anaconda, PyMc is installed with pip.

---

<div class="post-metadata">

**Author:** ![cluhmann](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cluhmann/32/3083_2.png) [@cluhmann](https://discourse.pymc.io/u/cluhmann)\
**Post date:** [November 25, 2024, 10:56pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/14 "2024-11-25T22:56:19Z")

</div>

What happens if you install via [the official installation instructions](https://www.pymc.io/projects/docs/en/latest/installation.html)?

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 26, 2024, 10:56am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/15 "2024-11-26T10:56:31Z")

</div>

Cluhmann,  
That actually fixed it.  
Thank you!

(very frustrating python’s package management!)

---

<div class="post-metadata">

**Author:** ![ricardoV94](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/ricardov94/32/5775_2.png) [@ricardoV94](https://discourse.pymc.io/u/ricardoV94)\
**Post date:** [November 26, 2024, 11:37am UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/16 "2024-11-26T11:37:49Z")

</div>

I have to say your case is very puzzling 😕

---

<div class="post-metadata">

**Author:** ![cosine](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.pymc.io/cosine/32/8777_2.png) [@cosine](https://discourse.pymc.io/u/cosine)\
**Post date:** [November 26, 2024, 4:19pm UTC](https://discourse.pymc.io/t/cores-not-optimally-used/16165/17 "2024-11-26T16:19:31Z")

</div>

Thanks again for the help!  
I guess there is some subtle change between versions how the multiprocessing via pipes is done…
