(threads)=

# Threads

The {ref}`threaded` algorithm supports the use of multiple threads.

```{name_supports}
:filter: threads
```

{ref}`threaded` shares most of its code with {ref}`serial` except for the high-level processing of
chunks which it performs in parallel using a thread pool, and the creation of {{ NumPy }} arrays is
limited to a single thread at a time.

```{note}
   The domain must be divided into chunks for multithreaded contouring.
```

Create a {py:class}`~.ThreadedContourGenerator` by calling
{py:func}`~.contour_generator` in the usual way, ensuring that the domain is chunked:

```python
>>> from contourpy import contour_generator
>>> import numpy as np
>>> z = np.ones((100, 50))  # Sample z data.
>>> cont_gen = contour_generator(z=z, name="threaded", chunk_count=5, thread_count=4)
>>> cont_gen.thread_count
4
>>> cont_gen.chunk_count
25
```

Here the 25 chunks will be divided up between the 4 threads.

The `thread_count` argument is optional, if not specified the default is `thread_count=0` which
means it will use the maximum number of threads available. This number can be checked using:

```python
>>> import contourpy
>>> contourpy.max_threads()
```

```{note}
   {py:meth}`.max_threads()` is implemented using the C++ function
   [std::thread::hardware_concurrency](https://en.cppreference.com/w/cpp/thread/thread/hardware_concurrency).
```

If you request more threads than the number of chunks, the thread count will be reduced accordingly.

```{warning}
   The order of processing chunks is not deterministic. If you use a {py:class}`~contourpy.LineType`
   or {py:class}`~contourpy.FillType` that do not arrange the results by chunk, the order of
   returned lines/polygons is also not deterministic. This includes `LineType.Separate`,
   `LineType.SeparateCode`, `FillType.OuterCode` and `FillType.OuterOffset`.
```
