Functions for thread management. More...
Functions | |
| SIMD_API size_t | SimdGetThreadNumber (void) |
| Gets current global thread number configured for Simd Library parallel algorithms. More... | |
| SIMD_API void | SimdSetThreadNumber (size_t threadNumber) |
| Sets number of threads used by Simd Library to parallelize some algorithms. More... | |
| template<class Function > | |
| void | Parallel (size_t begin, size_t end, const Function &function, size_t threadNumber, size_t blockAlign=1) |
| Splits a half-open index range across threads and waits until every part finishes. More... | |
Detailed Description
Functions for thread management.
Function Documentation
◆ SimdGetThreadNumber()
| size_t SimdGetThreadNumber | ( | void | ) |
Gets current global thread number configured for Simd Library parallel algorithms.
Returns the value set by SimdSetThreadNumber. By default this value is 1. When set, it is restricted to the range [1, std::thread::hardware_concurrency()].
- Returns
- current configured thread number.
◆ SimdSetThreadNumber()
| void SimdSetThreadNumber | ( | size_t | threadNumber | ) |
Sets number of threads used by Simd Library to parallelize some algorithms.
- Parameters
-
[in] threadNumber - a number of threads.
◆ Parallel()
| void Parallel | ( | size_t | begin, |
| size_t | end, | ||
| const Function & | function, | ||
| size_t | threadNumber, | ||
| size_t | blockAlign = 1 |
||
| ) |
Splits a half-open index range across threads and waits until every part finishes.
Divides [begin, end) into contiguous blocks and calls function(thread, blockBegin, blockEnd) for each block. thread is the zero-based index of that block. The blocks do not overlap and together cover [begin, end). blockEnd is exclusive. The call returns after every callback has returned.
The callback is usually a lambda with signature void(size_t thread, size_t blockBegin, size_t blockEnd). thread indexes a per-thread scratch buffer that the caller allocates for threadNumber slots. If the range is short, or if alignment yields fewer blocks than threadNumber, only the leading slots are used (indices 0, 1, ...). The other slots stay untouched.
threadNumber is limited by std::thread::hardware_concurrency(). If that value is 0, the limit is 0 and the call stays on the calling thread. The whole range is processed on the calling thread, as one call function(0, begin, end), when any of the following is true:
- threadNumber is 0 or 1;
- end - begin is less than or equal to size_t(blockAlign * 1.5) (for the default blockAlign of 1 this threshold is 1);
- SIMD_FUTURE_DISABLE is defined, so std::future is not used.
Otherwise every block except the last has a length that is a multiple of blockAlign. That length is (end - begin) divided by threadNumber, rounded up, and then rounded up to a multiple of blockAlign. The last block ends at end and may be shorter. The first block starts at begin, so alignment is relative to begin rather than to 0. blockAlign must be at least 1; the default is 1. end must be greater than or equal to begin. An empty range (begin == end) still performs one callback function(0, begin, begin).
In the multi-thread path the callbacks of one call run at the same time. They may read shared inputs, and they must not write the same memory. The usual pattern stores private scratch in a buffer indexed by thread. A callback must accept a short tail: the last block can be shorter than blockAlign.
Real usage:
- ResizerNearest and WarpAffine split destination rows [0, dstH) with blockAlign 1. The thread count comes from SimdGetThreadNumber. Nearest resize also caps it by the output size in bytes divided by 4 MB. WarpAffine indexes a per-thread buffer as buf + thread * size.
- GemmNN and GemmNT split the N dimension [0, N) with blockAlign equal to the micro-kernel width (_microN; it is 4 in GemmNT). thread selects the packed panel of that worker. A product with M * N * K below 256 * 256 * 256 * 2 sets threadNumber to 1 before the call.
- Descriptor comparison splits [0, N) and writes partial results to buffer[thread]. blockAlign is the inner step, or a multiple of it (1, 256 or 1024), so every block except the tail is a whole number of steps.
Using example:
- Parameters
-
[in] begin - the first index of the range (inclusive). [in] end - the index one past the last element of the range. [in] function - a callback function(thread, blockBegin, blockEnd) invoked for one block. [in] threadNumber - the maximum number of blocks. Limited by std::thread::hardware_concurrency(). [in] blockAlign - block length alignment, relative to begin. It must be at least 1. By default it is equal to 1.