# Build Python wheels with SMP tools for runtime backend selection

**URL:** https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268
**Category:** Development
**Created:** [February 3, 2026, 8:48pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268 "2026-02-03T20:48:51Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [February 3, 2026, 8:48pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/1 "2026-02-03T20:48:51Z")

</div>

According to the build settings:

> **[Build Settings - VTK documentation](https://docs.vtk.org/en/latest/build_instructions/build_settings.html)**

Users can set:

> - `VTK_SMP_IMPLEMENTATION_TYPE` (default `Sequential`): Set which SMPTools will be implemented by default. Must be either `Sequential`, `STDThread`, `OpenMP` or `TBB`. The backend can be changed at runtime if the desired backend has his option `VTK_SMP_ENABLE_<backend_name>` set to `ON`.

I don’t think this is enabled for the Python wheel builds that VTK releases. I suspect that `Sequential` is used by default for compatibility reasons, which is OK, but then does it make sense to otherwise build with the backends such that users can select a backend at runtime?

- VTK\_SMP\_ENABLE\_STDThread: ON
- VTK\_SMP\_ENABLE\_OpenMP: ON
- VTK\_SMP\_ENABLE\_TBB: ON

There seems to be technical reasons for why this is not done (see links below), but it would be nice for Python users in particular to be able to make use of the performance boost using the VTK wheels published on PyPI.

> [@Why doesn't VTK\_SMP\_IMPLEMENTATION\_TYPE default to STDThread?](https://discourse.vtk.org/t/why-doesnt-vtk-smp-implementation-type-default-to-stdthread/8293):
>
> Hi all, Why does VTK\_SMP\_IMPLEMENTATION\_TYPE default to Sequential instead of STDThread? Are there platforms where STDThread doesn’t exist/work? Cheers, Sean

[https://gitlab.kitware.com/vtk/vtk/-/issues/18668](https://gitlab.kitware.com/vtk/vtk/-/issues/18668)

If this should be tracked as a feature request, let me know and I’ll create an issue in GitLab.

---

<div class="post-metadata">

### Author: ![akaszynski](https://discourse.vtk.org/user_avatar/discourse.vtk.org/akaszynski/32/10751_2.png) [@akaszynski](https://discourse.vtk.org/u/akaszynski)
#### Post date: [February 4, 2026, 3:04am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/2 "2026-02-04T03:04:01Z")

</div>

BTW, I built `manylinux2014` compatible wheels with TBB enabled (by default) by following:

> <https://github.com/pyvista/pyvista-wheels/issues/11>
>
> This is mostly how to build TBB compatible wheels on \`manylinux2024\`:
> 
> \`\`\`bash
> \#…!/usr/bin/env bash
> set -e
> 
> mkdir -p build
> cd build
> 
> yum install -y ninja-build cmake wget
> 
> \# could also try https://github.com/uxlfoundation/oneTBB/releases/v2021.1.1
> wget https://github.com/uxlfoundation/oneTBB/releases/download/v2020.3/tbb-2020.3-lin.tgz
> tar xf tbb-2020.3-lin.tgz -C /opt
> 
> \# fairly sure that LD\_LIBRARY\_PATH lets auditwheel find tbb, but you might be able to get away without it
> export TBB\_ROOT=/opt/tbb
> export LD\_LIBRARY\_PATH=/opt/tbb/lib/intel64/gcc4.8:$LD\_LIBRARY\_PATH
> 
> get\_python\_bin() {
> local version="$1"
> echo "/opt/python/cp${version//.}-cp${version//.}/bin/python"
> }
> 
> PYBIN=$(get\_python\_bin "3.12")
> 
> cmake -GNinja \\
> -DVTK\_SMP\_IMPLEMENTATION\_TYPE=TBB \\
> -DCMAKE\_PREFIX\_PATH=/opt/tbb \\
> -DCMAKE\_BUILD\_TYPE=Release \\
> -DVTK\_BUILD\_TESTING=OFF \\
> -DVTK\_BUILD\_DOCUMENTATION=OFF \\
> -DVTK\_BUILD\_EXAMPLES=OFF \\
> -DVTK\_MODULE\_ENABLE\_VTK\_PythonInterpreter:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_WebCore:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_WebGLExporter:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_WebPython:STRING=NO \\
> -DVTK\_WHEEL\_BUILD=ON \\
> -DVTK\_MODULE\_ENABLE\_VTK\_CommonArchive:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_DomainsMicroscopy:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_FiltersONNX:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_FiltersOpenTURNS:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_FiltersReebGraph:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOADIOS2:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOAlembic:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOFFMPEG:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOGDAL:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOLAS:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOMySQL:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOODBC:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOOpenVDB:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOPDAL:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOPostgreSQL:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_InfovisBoost:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_InfovisBoostGraphAlgorithms:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingFreeTypeFontConfig:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingOpenVR:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingOpenXR:STRING=NO \\
> -DVTK\_USE\_PCH:BOOL=OFF \\
> -DVTK\_ENABLE\_REMOTE\_MODULES:BOOL=OFF \\
> -DVTK\_USE\_PCH:BOOL=OFF \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingRayTracing:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingZSpace:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_RenderingMatplotlib:STRING=YES \\
> -DVTK\_MODULE\_ENABLE\_VTK\_fides:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_xdmf3:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOOCCT:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOUSD:STRING=NO \\
> -DVTK\_MODULE\_ENABLE\_VTK\_IOEnSight:STRING=NO \\
> -DVTK\_ENABLE\_CATALYST:BOOL=OFF \\
> -DPython3\_EXECUTABLE=$PYBIN ../
> 
> ninja-build
> 
> 
> \# build wheel in dist
> $PYBIN -m pip install wheel setuptools
> 
> auditwheel repair dist/\*.whl
> \`\`\`

This script was run in a `manylinux2014` docker image. You have to use an older version of TBB (as VTK currently does) as the modern one doesn’t support the older toolchain used in `manylinux2014`.

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [February 4, 2026, 8:01am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/3 "2026-02-04T08:01:00Z")

</div>

TBH I dont think this was considered specifically, I think you could just try adding `VTK_SMP_ENABLE_TBB` to the Wheel CI conf and see how it goes.

---

<div class="post-metadata">

### Author: ![hakostra](https://discourse.vtk.org/user_avatar/discourse.vtk.org/hakostra/32/2990_2.png) [@hakostra](https://discourse.vtk.org/u/hakostra)
#### Post date: [February 4, 2026, 9:52am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/4 "2026-02-04T09:52:50Z")

</div>

I have no exact numbers immediately at hand, but experimented with STDThread/TBB/OpenMP SMP implementations in VTK a while ago. My results did _not_ show big differences between the implementations. More or less in line with the numbers shown here: [https://www.kitware.com/vtk-shared-memory-parallelism-tools-2021-updates/](https://www.kitware.com/vtk-shared-memory-parallelism-tools-2021-updates/)

I see the most recent 9.6.0rc3 has the STDThread backend available, but not enabled by default. The two others are unavailable.

If there are no significant performance gains in the OpenMP or TBB backends, I see no reason to have them in the Python wheels. Adding this will add to the total size and you will need to add in and pack the supporting runtime libraries.

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [February 4, 2026, 10:46am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/5 "2026-02-04T10:46:55Z")

</div>

Very good point @hakostra , I forgot that STDThread is enabled by default, which makes it already available to use.

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [February 4, 2026, 11:07am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/6 "2026-02-04T11:07:07Z")

</div>

For simplicity, I would just use std:thread for now.

However, note that anytime the workload of worklets varies significantly, so that load balancing is important, significant performance differences are often realized between TBB and std::thread. I am currently seeing 50-75% speed increases (using TBB vs stdthread) on some Voronoi-based meshing applications.

---

<div class="post-metadata">

### Author: ![akaszynski](https://discourse.vtk.org/user_avatar/discourse.vtk.org/akaszynski/32/10751_2.png) [@akaszynski](https://discourse.vtk.org/u/akaszynski)
#### Post date: [February 4, 2026, 5:18pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/7 "2026-02-04T17:18:03Z")

</div>

I’m seeing similar gains (~50%) using TBB vs stdthread for `vtkGeometryFilter`.

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [February 4, 2026, 6:11pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/8 "2026-02-04T18:11:56Z")

</div>

> [@mwestphal](#):
>
> TBH I dont think this was considered specifically, I think you could just try adding `VTK_SMP_ENABLE_TBB` to the Wheel CI conf and see how it goes.

I tried adding this here:  
[https://gitlab.kitware.com/vtk/vtk/-/merge\_requests/12884](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12884)

---

<div class="post-metadata">

### Author: ![user27182](https://discourse.vtk.org/user_avatar/discourse.vtk.org/user27182/32/10104_2.png) [@user27182](https://discourse.vtk.org/u/user27182)
#### Post date: [February 4, 2026, 8:52pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/9 "2026-02-04T20:52:34Z")

</div>

> [@user27182](#):
>
> I tried adding this here:  
> [https://gitlab.kitware.com/vtk/vtk/-/merge\_requests/12884](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12884)

Based on discussion in that MR, enabling TBB by default doesn’t seem like it’s currently viable, and users will need to build from source themselves to use it.

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [February 8, 2026, 1:58pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/10 "2026-02-08T13:58:39Z")

</div>

Sorry for being late to this party and missing that thread (no pun intended!!!). Note that there is a TBB wheel on linux: [tbb · PyPI](https://pypi.org/project/tbb/)  
So it is totally possible to use non-mangle TBB on Linux. There seems to be a TBB wheel that shows up on Homebrew on the mac. Not sure where it comes from.  
Using TBB should be possible as long as we are willing to create and maintain TBB wheels for Mac Silicon and Windows. I suggest that we do that.

---

<div class="post-metadata">

### Author: ![hakostra](https://discourse.vtk.org/user_avatar/discourse.vtk.org/hakostra/32/2990_2.png) [@hakostra](https://discourse.vtk.org/u/hakostra)
#### Post date: [February 8, 2026, 4:51pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/11 "2026-02-08T16:51:59Z")

</div>

There is no wheel/build for ARM (aarch64), even on Linux. I guess this is a strategic/political choice from Intel, who seems to be the publisher of this package, to only build for x86. I see that as a big disadvantage, as arm is becoming more and more important. If one sets up to maintain repos/libraries/packages for Mac and Windows, one should also do it for ARM.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [February 9, 2026, 1:58am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/12 "2026-02-09T01:58:20Z")

</div>

That is fine; the `tbb` wheel should ship the TBB libraries. The question is how other wheels that _also_ want to use TBB’s C++ API should get access to the same libraries as that wheel.

---

<div class="post-metadata">

### Author: ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)
#### Post date: [February 9, 2026, 12:48pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/13 "2026-02-09T12:48:53Z")

</div>

Here’s an example of how Intel’s own `tbb4py` pypi package uses the libraries from the `tbb` pypi package.

E.g. for linux, `tbb4py` has a `_api.cpython-310-x86_64-linux-gnu.so` extension module that links to the `libtbb.so` library provided by the `tbb` package.

It does this by using an `RPATH` of `$ORIGIN/../../..`, i.e. it assumes a specific directory layout where `site-packages` is located within the `lib` (or `lib64` on rhel?) that contains the tbb library:

```plaintext
ldd /my-venv/lib/python3.10/site-packages/tbb/_api.cpython-310-x86_64-linux-gnu.so

	libtbb.so.12 => /my-venv/lib/python3.10/site-packages/tbb/../../../libtbb.so.12 (0x00007ff9b5e00000)
	libirml.so.1 => /my-venv/lib/python3.10/site-packages/tbb/../../../libirml.so.1 (0x00007ff9b5a00000)
	libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff9b57d4000)
    etc.

```

> **tbb package contents, for reference:**
>
> ```plaintext
> lib/libtbb.so*
> lib/libtbbbind.so*
> lib/libtbbbind_2_0.so*
> lib/libtbbbind_2_5.so*
> lib/libtbbmalloc.so*
> lib/libtbbmalloc_proxy.so*
> share/doc/tbb/licensing/third-party-programs.txt
> 
> ```

> **tbb4py package contents, for reference:**
>
> ```plaintext
> lib/libirml.so*
> lib/python3.10/site-packages/TBB.py
> lib/python3.10/site-packages/tbb/_api.cpython-310-x86_64-linux-gnu.so
> lib/python3.10/site-packages/tbb/api.py
> lib/python3.10/site-packages/tbb/ __init__.py
> lib/python3.10/site-packages/tbb/ __main__.py
> lib/python3.10/site-packages/tbb/pool.py
> lib/python3.10/site-packages/tbb/test.py
> 
> ```

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [February 9, 2026, 1:58pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/14 "2026-02-09T13:58:48Z")

</div>

Yes, the $ORIGIN thingy is the official way that PyPi folks want you to handle this.

---

<div class="post-metadata">

### Author: ![berk.geveci](https://discourse.vtk.org/user_avatar/discourse.vtk.org/berk.geveci/32/3146_2.png) [@berk.geveci](https://discourse.vtk.org/u/berk.geveci)
#### Post date: [February 9, 2026, 1:59pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/15 "2026-02-09T13:59:50Z")

</div>

Yup. We would have to make and ship those. I can’t image it being too hard since there is already one for X86 linux and we build TBB all the time anyway…

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [February 9, 2026, 4:20pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/16 "2026-02-09T16:20:24Z")

</div>

Yes, `tbb` builds for the missing platforms just fine. I think it’d be better to engage the existing maintainers to see what’d it take to have them included in their normal release process to start. If they reject, we can either make it conditional in `vtk` or work on doing it ourselves.

---

<div class="post-metadata">

### Author: ![Michael\_Jackson](https://discourse.vtk.org/user_avatar/discourse.vtk.org/michael_jackson/32/61_2.png) [@Michael\_Jackson](https://discourse.vtk.org/u/Michael_Jackson)
#### Post date: [February 9, 2026, 10:02pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/17 "2026-02-09T22:02:17Z")

</div>

What about OneAPI which includes TBB. We use that for our ARM builds (MacOS) and it seems to work just fine. Granted we use it through vcpkg.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)
#### Post date: [February 10, 2026, 1:46am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/18 "2026-02-10T01:46:19Z")

</div>

OneAPI is the umbrella project TBB lives within, yes. The issue is making a build available through `pip install`.

---

<div class="post-metadata">

### Author: ![vbolea](https://discourse.vtk.org/user_avatar/discourse.vtk.org/vbolea/32/4060_2.png) [@vbolea](https://discourse.vtk.org/u/vbolea)
#### Post date: [February 21, 2026, 12:20am UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/19 "2026-02-21T00:20:59Z")

</div>

I have just forwarded this question to the OpenTBB project: [Missing arm64 wheels for the Pypi TBB package · Issue #1972 · uxlfoundation/oneTBB · GitHub](https://github.com/uxlfoundation/oneTBB/issues/1972)

---

<div class="post-metadata">

### Author: ![akaszynski](https://discourse.vtk.org/user_avatar/discourse.vtk.org/akaszynski/32/10751_2.png) [@akaszynski](https://discourse.vtk.org/u/akaszynski)
#### Post date: [April 8, 2026, 7:08pm UTC](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268/20 "2026-04-08T19:08:17Z")

</div>

A quick note for anyone here looking to speed up filters that benefit from parallelism like `vtkFlyingEdges3D`, the following works on the latest (v9.6.1) VTK wheels:

```py
import vtk

tool = vtk.vtkSMPTools()
backend = "STDThread" # one of "Sequential", "STDThread", "TBB" or "OpenMP"
available = tool.SetBackend(backend)
if not available:
    raise RuntimeError(f"{backend} not available")
tool.Initialize(24) # number of threads

...

# use vtkFlyingEdges3D or pyvista's:
# grid.contour(2, method="flying_edges", rng=(200, 230))

```

[Next page](https://discourse.vtk.org/t/build-python-wheels-with-smp-tools-for-runtime-backend-selection/16268.md?page=2)
