Coverage Report

Created: 2026-08-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xnnpack/build/pthreadpool-source/include/pthreadpool.h
Line
Count
Source
1
// Copyright (c) 2017 Facebook Inc.
2
// Copyright (c) 2015-2017 Georgia Institute of Technology
3
// All rights reserved.
4
//
5
// Copyright 2019 Google LLC
6
//
7
// This source code is licensed under the BSD-style license found in the
8
// LICENSE file in the root directory of this source tree.
9
10
#ifndef __PTHREADPOOL_INCLUDE_PTHREADPOOL_H_
11
#define __PTHREADPOOL_INCLUDE_PTHREADPOOL_H_
12
13
#include <stdbool.h>
14
#include <stddef.h>
15
#include <stdint.h>
16
17
typedef struct pthreadpool* pthreadpool_t;
18
19
typedef void (*pthreadpool_task_1d_t)(void*, size_t);
20
typedef void (*pthreadpool_task_1d_with_thread_t)(void*, size_t, size_t);
21
typedef void (*pthreadpool_task_1d_tile_1d_t)(void*, size_t, size_t);
22
typedef void (*pthreadpool_task_1d_tile_1d_dynamic_t)(void*, size_t, size_t);
23
typedef void (*pthreadpool_task_1d_tile_1d_dynamic_with_id_t)(void*, uint32_t,
24
                                                              size_t, size_t);
25
typedef void (*pthreadpool_task_2d_t)(void*, size_t, size_t);
26
typedef void (*pthreadpool_task_2d_with_thread_t)(void*, size_t, size_t,
27
                                                  size_t);
28
typedef void (*pthreadpool_task_2d_tile_1d_t)(void*, size_t, size_t, size_t);
29
typedef void (*pthreadpool_task_2d_tile_1d_dynamic_t)(void*, size_t, size_t,
30
                                                      size_t);
31
typedef void (*pthreadpool_task_2d_tile_2d_t)(void*, size_t, size_t, size_t,
32
                                              size_t);
33
typedef void (*pthreadpool_task_2d_tile_2d_dynamic_t)(void*, size_t, size_t,
34
                                                      size_t, size_t);
35
typedef void (*pthreadpool_task_3d_t)(void*, size_t, size_t, size_t);
36
typedef void (*pthreadpool_task_3d_tile_1d_t)(void*, size_t, size_t, size_t,
37
                                              size_t);
38
typedef void (*pthreadpool_task_3d_tile_1d_with_thread_t)(void*, size_t, size_t,
39
                                                          size_t, size_t,
40
                                                          size_t);
41
typedef void (*pthreadpool_task_3d_tile_1d_dynamic_t)(void*, size_t, size_t,
42
                                                      size_t, size_t);
43
typedef void (*pthreadpool_task_3d_tile_2d_t)(void*, size_t, size_t, size_t,
44
                                              size_t, size_t);
45
typedef void (*pthreadpool_task_3d_tile_2d_dynamic_t)(void*, size_t, size_t,
46
                                                      size_t, size_t, size_t);
47
typedef void (*pthreadpool_task_4d_t)(void*, size_t, size_t, size_t, size_t);
48
typedef void (*pthreadpool_task_4d_tile_1d_t)(void*, size_t, size_t, size_t,
49
                                              size_t, size_t);
50
typedef void (*pthreadpool_task_4d_tile_2d_t)(void*, size_t, size_t, size_t,
51
                                              size_t, size_t, size_t);
52
typedef void (*pthreadpool_task_4d_tile_2d_dynamic_t)(void*, size_t, size_t,
53
                                                      size_t, size_t, size_t,
54
                                                      size_t);
55
typedef void (*pthreadpool_task_5d_t)(void*, size_t, size_t, size_t, size_t,
56
                                      size_t);
57
typedef void (*pthreadpool_task_5d_tile_1d_t)(void*, size_t, size_t, size_t,
58
                                              size_t, size_t, size_t);
59
typedef void (*pthreadpool_task_5d_tile_2d_t)(void*, size_t, size_t, size_t,
60
                                              size_t, size_t, size_t, size_t);
61
typedef void (*pthreadpool_task_6d_t)(void*, size_t, size_t, size_t, size_t,
62
                                      size_t, size_t);
63
typedef void (*pthreadpool_task_6d_tile_1d_t)(void*, size_t, size_t, size_t,
64
                                              size_t, size_t, size_t, size_t);
65
typedef void (*pthreadpool_task_6d_tile_2d_t)(void*, size_t, size_t, size_t,
66
                                              size_t, size_t, size_t, size_t,
67
                                              size_t);
68
69
typedef void (*pthreadpool_task_1d_with_id_t)(void*, uint32_t, size_t);
70
typedef void (*pthreadpool_task_2d_tile_1d_with_id_t)(void*, uint32_t, size_t,
71
                                                      size_t, size_t);
72
typedef void (*pthreadpool_task_2d_tile_1d_dynamic_with_id_t)(void*, uint32_t,
73
                                                              size_t, size_t,
74
                                                              size_t);
75
typedef void (*pthreadpool_task_2d_tile_2d_with_id_t)(void*, uint32_t, size_t,
76
                                                      size_t, size_t, size_t);
77
typedef void (*pthreadpool_task_2d_tile_2d_dynamic_with_id_t)(void*, uint32_t,
78
                                                              size_t, size_t,
79
                                                              size_t, size_t);
80
typedef void (*pthreadpool_task_3d_tile_1d_with_id_t)(void*, uint32_t, size_t,
81
                                                      size_t, size_t, size_t);
82
typedef void (*pthreadpool_task_3d_tile_1d_dynamic_with_id_t)(void*, uint32_t,
83
                                                              size_t, size_t,
84
                                                              size_t, size_t);
85
typedef void (*pthreadpool_task_3d_tile_2d_with_id_t)(void*, uint32_t, size_t,
86
                                                      size_t, size_t, size_t,
87
                                                      size_t);
88
typedef void (*pthreadpool_task_3d_tile_2d_dynamic_with_id_t)(void*, uint32_t,
89
                                                              size_t, size_t,
90
                                                              size_t, size_t,
91
                                                              size_t);
92
typedef void (*pthreadpool_task_4d_tile_2d_with_id_t)(void*, uint32_t, size_t,
93
                                                      size_t, size_t, size_t,
94
                                                      size_t, size_t);
95
typedef void (*pthreadpool_task_4d_tile_2d_dynamic_with_id_t)(void*, uint32_t,
96
                                                              size_t, size_t,
97
                                                              size_t, size_t,
98
                                                              size_t, size_t);
99
100
typedef void (*pthreadpool_task_1d_tile_1d_dynamic_with_id_with_thread_t)(
101
    void*, uint32_t, size_t, size_t, size_t);
102
typedef void (*pthreadpool_task_2d_tile_1d_with_id_with_thread_t)(
103
    void*, uint32_t, size_t, size_t, size_t, size_t);
104
typedef void (*pthreadpool_task_2d_tile_1d_dynamic_with_id_with_thread_t)(
105
    void*, uint32_t, size_t, size_t, size_t, size_t);
106
typedef void (*pthreadpool_task_3d_tile_1d_with_id_with_thread_t)(
107
    void*, uint32_t, size_t, size_t, size_t, size_t, size_t);
108
typedef void (*pthreadpool_task_3d_tile_1d_dynamic_with_id_with_thread_t)(
109
    void*, uint32_t, size_t, size_t, size_t, size_t, size_t);
110
111
/**
112
 * Disable support for denormalized numbers to the maximum extent possible for
113
 * the duration of the computation.
114
 *
115
 * Handling denormalized floating-point numbers is often implemented in
116
 * microcode, and incurs significant performance degradation. This hint
117
 * instructs the thread pool to disable support for denormalized numbers before
118
 * running the computation by manipulating architecture-specific control
119
 * registers, and restore the initial value of control registers after the
120
 * computation is complete. The thread pool temporary disables denormalized
121
 * numbers on all threads involved in the computation (i.e. the caller threads,
122
 * and potentially worker threads).
123
 *
124
 * Disabling denormalized numbers may have a small negative effect on results'
125
 * accuracy. As various architectures differ in capabilities to control
126
 * processing of denormalized numbers, using this flag may also hurt results'
127
 * reproducibility across different instruction set architectures.
128
 */
129
0
#define PTHREADPOOL_FLAG_DISABLE_DENORMALS 0x00000001
130
131
/**
132
 * Yield worker threads to the system scheduler after the operation is finished.
133
 *
134
 * Force workers to use kernel wait (instead of active spin-wait by default) for
135
 * new commands after this command is processed. This flag affects only the
136
 * immediate next operation on this thread pool. To make the thread pool always
137
 * use kernel wait, pass this flag to all parallelization functions.
138
 *
139
 * Note: This flag is currently ignored as yielding the worker threads after a
140
 * fixed number of spin-wait iterations is currently the default behaviour.
141
 */
142
0
#define PTHREADPOOL_FLAG_YIELD_WORKERS 0x00000002
143
144
/**
145
 * If worker threads are provided by an external @a pthreadpool_executor,
146
 * release them back to the executor instead of spinning for a fixed number of
147
 * iterations first.
148
 */
149
0
#define PTHREADPOOL_FLAG_DONT_SPIN_WORKERS 0x00000004
150
151
// Disable function sanitization here. The thread pool calls these functions
152
// via function pointers with void* contexts, which triggers false positives in
153
// the function sanitizer when casting and calling the actual context type.
154
#if defined(__clang__) && __has_attribute(no_sanitize)
155
#define PTHREADPOOL_NO_SANITIZE_FUNCTION \
156
  __attribute__((no_sanitize("function")))
157
#else
158
#define PTHREADPOOL_NO_SANITIZE_FUNCTION
159
#endif
160
161
#ifdef __cplusplus
162
extern "C" {
163
#endif
164
165
/// An abstract interface of a parallel task executor.
166
struct pthreadpool_executor {
167
  /// Get the number of tasks that can be executed concurrently.
168
  int (*num_threads)(void* executor_context);
169
170
  /// Schedule `task` to be called, with `context` as its argument.
171
  void (*schedule)(void* executor_context, void* context,
172
                   void (*task)(void* context));
173
};
174
175
/**
176
 * Create a thread pool with the specified number of threads.
177
 *
178
 * @param  threads_count  the number of threads in the thread pool.
179
 *    A value of 0 has special interpretation: it creates a thread pool with as
180
 *    many threads as there are logical processors in the system.
181
 *
182
 * @return  A pointer to an opaque thread pool object if the call is
183
 *    successful, or NULL pointer if the call failed.
184
 */
185
pthreadpool_t pthreadpool_create(size_t threads_count);
186
187
/**
188
 * Create a thread pool with a given @a pthreadpool_executor and a maximum
189
 * specified number of threads.
190
 *
191
 * For each call to a `pthreadpool_parallelize_*` function, the minimum of @a
192
 * max_num_threads and @a executor->num_threads(executor_context) calls to @a
193
 * executor->schedule(executor_context, ...) will be executed, potentially
194
 * lasting for the entire duration of the `pthreadpool_parallelize_*` call.
195
 *
196
 * @param executor          A pointer to a @a pthreadpool_executor object that
197
 *                          will be used to determine the number of extra
198
 *                          threads (plus the calling thread), and provide the
199
 *                          threads itself, for each call to a
200
 *                          `pthreadpool_parallelize_*` function.
201
 * @param executor_context  A pointer to the context that will be passed to the
202
 *                          functions in the @a executor object.
203
 * @param max_num_thread    The maximum number of threads in the thread pool.
204
 *                          A value of 0 has special interpretation: it creates
205
 *                          a thread pool with as many threads as there are
206
 *                          logical processors in the system.
207
 *
208
 * @return  A pointer to an opaque thread pool object if the call is
209
 *    successful, or NULL pointer if the call failed.
210
 */
211
pthreadpool_t pthreadpool_create_v2(struct pthreadpool_executor* executor,
212
                                    void* executor_context,
213
                                    size_t max_num_threads);
214
215
/**
216
 * Query the number of threads in a thread pool.
217
 *
218
 * @param  threadpool  the thread pool to query.
219
 *
220
 * @return  The number of threads in the thread pool.
221
 */
222
size_t pthreadpool_get_threads_count(pthreadpool_t threadpool);
223
224
/**
225
 * Try to set the number of threads in a thread pool.
226
 *
227
 * The number of threads can be at most the number of threads with which the @a
228
 * threadpool was created, or the number of threads provided by the @a
229
 * pthreadpool_executor if the threadpool was created with @a
230
 * pthreadpool_create_v2.
231
 *
232
 * Trying to set a larger value will set and return the maximum possible value.
233
 *
234
 * @param  threadpool   The thread pool to query.
235
 * @param  num_threads  The desired number of threads. A value of 0 sets the
236
 *                      number of threads to the maximum available, i.e. the
237
 *                      value used when the @a threadpool was created.
238
 *
239
 * @return  The updated number of threads in the thread pool.
240
 */
241
size_t pthreadpool_set_threads_count(pthreadpool_t threadpool,
242
                                     size_t num_threads);
243
244
/**
245
 * Release any threads borrowed from an @a pthreadpool_executor.
246
 *
247
 * If the @a threadpool was created with @a pthreadpool_create_v2, this function
248
 * returns any threads acquired during execution to the associated @a
249
 * pthreadpool_executor.
250
 *
251
 * Threads will be re-acquired as needed on the next call to a
252
 * `pthreadpool_parallelize_*` function.
253
 *
254
 * If the @a threadpool was _not_ created with @a pthreadpool_create_v2, then
255
 * this function does nothing.
256
 *
257
 * @param  threadpool   the thread pool on which to release the executor
258
 *                      threads.
259
 */
260
void pthreadpool_release_executor_threads(struct pthreadpool* threadpool);
261
262
/**
263
 * Updates a thread pool with a given @a pthreadpool_executor.
264
 *
265
 * @param threadpool        The thread pool in which to replace the executor.
266
 * @param executor          A pointer to a @a pthreadpool_executor object that
267
 *                          will be used to determine the number of extra
268
 *                          threads (plus the calling thread), and provide the
269
 *                          threads itself, for each call to a
270
 *                          `pthreadpool_parallelize_*` function.
271
 * @param executor_context  A pointer to the context that will be passed to the
272
 *                          functions in the @a executor object.
273
 *
274
 * @return  @c true if the @a executor was successfully swapped, and @c false if
275
 * it was not, e.g. because the current and nex @a executor and @a
276
 * executor_context are identical.
277
 */
278
bool pthreadpool_update_executor(pthreadpool_t threadpool,
279
                                 struct pthreadpool_executor* executor,
280
                                 void* executor_context);
281
282
/**
283
 * Process items on a 1D grid.
284
 *
285
 * The function implements a parallel version of the following snippet:
286
 *
287
 *   for (size_t i = 0; i < range; i++)
288
 *     function(context, i);
289
 *
290
 * When the function returns, all items have been processed and the thread pool
291
 * is ready for a new task.
292
 *
293
 * @note If multiple threads call this function with the same thread pool, the
294
 *    calls are serialized.
295
 *
296
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
297
 *    is NULL, all items are processed serially on the calling thread.
298
 * @param function    the function to call for each item.
299
 * @param context     the first argument passed to the specified function.
300
 * @param range       the number of items on the 1D grid to process. The
301
 *    specified function will be called once for each item.
302
 * @param flags       a bitwise combination of zero or more optional flags
303
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
304
 */
305
void pthreadpool_parallelize_1d(pthreadpool_t threadpool,
306
                                pthreadpool_task_1d_t function, void* context,
307
                                size_t range, uint32_t flags);
308
309
/**
310
 * Process items on a 1D grid passing along the current thread id.
311
 *
312
 * The function implements a parallel version of the following snippet:
313
 *
314
 *   for (size_t i = 0; i < range; i++)
315
 *     function(context, thread_index, i);
316
 *
317
 * When the function returns, all items have been processed and the thread pool
318
 * is ready for a new task.
319
 *
320
 * @note If multiple threads call this function with the same thread pool, the
321
 *    calls are serialized.
322
 *
323
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
324
 *    is NULL, all items are processed serially on the calling thread.
325
 * @param function    the function to call for each item.
326
 * @param context     the first argument passed to the specified function.
327
 * @param range       the number of items on the 1D grid to process. The
328
 *    specified function will be called once for each item.
329
 * @param flags       a bitwise combination of zero or more optional flags
330
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
331
 */
332
void pthreadpool_parallelize_1d_with_thread(
333
    pthreadpool_t threadpool, pthreadpool_task_1d_with_thread_t function,
334
    void* context, size_t range, uint32_t flags);
335
336
/**
337
 * Process items on a 1D grid using a microarchitecture-aware task function.
338
 *
339
 * The function implements a parallel version of the following snippet:
340
 *
341
 *   uint32_t uarch_index = cpuinfo_initialize() ?
342
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
343
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
344
 *   for (size_t i = 0; i < range; i++)
345
 *     function(context, uarch_index, i);
346
 *
347
 * When the function returns, all items have been processed and the thread pool
348
 * is ready for a new task.
349
 *
350
 * @note If multiple threads call this function with the same thread pool, the
351
 *    calls are serialized.
352
 *
353
 * @param threadpool           the thread pool to use for parallelisation. If
354
 *    threadpool is NULL, all items are processed serially on the calling
355
 *    thread.
356
 * @param function             the function to call for each item.
357
 * @param context              the first argument passed to the specified
358
 *    function.
359
 * @param default_uarch_index  the microarchitecture index to use when
360
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
361
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
362
 *    max_uarch_index value.
363
 * @param max_uarch_index      the maximum microarchitecture index expected by
364
 *    the specified function. If the index returned by
365
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
366
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
367
 * @param range                the number of items on the 1D grid to process.
368
 *    The specified function will be called once for each item.
369
 * @param flags                a bitwise combination of zero or more optional
370
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
371
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
372
 */
373
void pthreadpool_parallelize_1d_with_uarch(
374
    pthreadpool_t threadpool, pthreadpool_task_1d_with_id_t function,
375
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
376
    size_t range, uint32_t flags);
377
378
/**
379
 * Process items on a 1D grid with specified maximum tile size.
380
 *
381
 * The function implements a parallel version of the following snippet:
382
 *
383
 *   for (size_t i = 0; i < range; i += tile)
384
 *     function(context, i, min(range - i, tile));
385
 *
386
 * When the call returns, all items have been processed and the thread pool is
387
 * ready for a new task.
388
 *
389
 * @note If multiple threads call this function with the same thread pool,
390
 *    the calls are serialized.
391
 *
392
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
393
 *    is NULL, all items are processed serially on the calling thread.
394
 * @param function    the function to call for each tile.
395
 * @param context     the first argument passed to the specified function.
396
 * @param range       the number of items on the 1D grid to process.
397
 * @param tile        the maximum number of items on the 1D grid to process in
398
 *    one function call.
399
 * @param flags       a bitwise combination of zero or more optional flags
400
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
401
 */
402
void pthreadpool_parallelize_1d_tile_1d(pthreadpool_t threadpool,
403
                                        pthreadpool_task_1d_tile_1d_t function,
404
                                        void* context, size_t range,
405
                                        size_t tile, uint32_t flags);
406
407
/**
408
 * Process items on a 1D grid with specified prefered tile size.
409
 *
410
 * The function repeatedly calls
411
 *
412
 *   function(context, i, count)
413
 *
414
 * in parallel where `i` is in the range `[0, range)` and a multiple of the
415
 * provided @a tile and `count` is an integer multiple of @a tile unless `i
416
 * + count == range`.
417
 *
418
 * The `count`s are chosen such as to minimize the number of calls to @a
419
 * function while keeping the computation load balanced across all threads.
420
 *
421
 * When the call returns, all items have been processed and the thread pool is
422
 * ready for a new task.
423
 *
424
 * @note If multiple threads call this function with the same thread pool,
425
 *    the calls are serialized.
426
 *
427
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
428
 *    is NULL, all items are processed serially on the calling thread.
429
 * @param function    the function to call for each interval of the given range.
430
 * @param context     the first argument passed to the specified function.
431
 * @param range       the number of items on the 1D grid to process.
432
 * @param tile        the preferred multiple number of items on the 1D grid to
433
 *     process in each function call.
434
 * @param flags       a bitwise combination of zero or more optional flags
435
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
436
 */
437
void pthreadpool_parallelize_1d_tile_1d_dynamic(
438
    pthreadpool_t threadpool, pthreadpool_task_1d_tile_1d_dynamic_t function,
439
    void* context, size_t range, size_t tile, uint32_t flags);
440
441
/**
442
 * Process items on a 1D grid with specified prefered tile size, passing along
443
 * the current thread id.
444
 *
445
 * The function repeatedly calls
446
 *
447
 *   function(context, thread_id, i, count)
448
 *
449
 * in parallel where `i` is in the range `[0, range)` and a multiple of the
450
 * provided @a tile and `count` is an integer multiple of @a tile unless `i
451
 * + count == range`.
452
 *
453
 * The `count`s are chosen such as to minimize the number of calls to @a
454
 * function while keeping the computation load balanced across all threads.
455
 *
456
 * When the call returns, all items have been processed and the thread pool is
457
 * ready for a new task.
458
 *
459
 * @note If multiple threads call this function with the same thread pool,
460
 *    the calls are serialized.
461
 *
462
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
463
 *    is NULL, all items are processed serially on the calling thread.
464
 * @param function    the function to call for each interval of the given range.
465
 * @param context     the first argument passed to the specified function.
466
 * @param range       the number of items on the 1D grid to process.
467
 * @param tile        the preferred multiple number of items on the 1D grid to
468
 *     process in each function call.
469
 * @param flags       a bitwise combination of zero or more optional flags
470
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
471
 */
472
void pthreadpool_parallelize_1d_tile_1d_dynamic_with_thread(
473
    pthreadpool_t threadpool,
474
    pthreadpool_task_1d_tile_1d_dynamic_with_id_t function, void* context,
475
    size_t range, size_t tile, uint32_t flags);
476
477
/**
478
 * Process items on a 1D grid with specified prefered tile size, passing along
479
 * the current uarch index and thread id.
480
 *
481
 * The function repeatedly calls
482
 *
483
 *   function(context, uarch_index, thread_id, i, count)
484
 *
485
 * in parallel where `i` is in the range `[0, range)` and a multiple of the
486
 * provided @a tile and `count` is an integer multiple of @a tile unless `i
487
 * + count == range`.
488
 *
489
 * The `count`s are chosen such as to minimize the number of calls to @a
490
 * function while keeping the computation load balanced across all threads.
491
 *
492
 * When the call returns, all items have been processed and the thread pool is
493
 * ready for a new task.
494
 *
495
 * @note If multiple threads call this function with the same thread pool,
496
 *    the calls are serialized.
497
 *
498
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
499
 *    is NULL, all items are processed serially on the calling thread.
500
 * @param function    the function to call for each interval of the given range.
501
 * @param context     the first argument passed to the specified function.
502
 * @param range       the number of items on the 1D grid to process.
503
 * @param tile        the preferred multiple number of items on the 1D grid to
504
 *     process in each function call.
505
 * @param flags       a bitwise combination of zero or more optional flags
506
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
507
 */
508
void pthreadpool_parallelize_1d_tile_1d_dynamic_with_uarch_with_thread(
509
    pthreadpool_t threadpool,
510
    pthreadpool_task_1d_tile_1d_dynamic_with_id_with_thread_t function,
511
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
512
    size_t range, size_t tile, uint32_t flags);
513
514
/**
515
 * Process items on a 2D grid.
516
 *
517
 * The function implements a parallel version of the following snippet:
518
 *
519
 *   for (size_t i = 0; i < range_i; i++)
520
 *     for (size_t j = 0; j < range_j; j++)
521
 *       function(context, i, j);
522
 *
523
 * When the function returns, all items have been processed and the thread pool
524
 * is ready for a new task.
525
 *
526
 * @note If multiple threads call this function with the same thread pool, the
527
 *    calls are serialized.
528
 *
529
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
530
 *    is NULL, all items are processed serially on the calling thread.
531
 * @param function    the function to call for each item.
532
 * @param context     the first argument passed to the specified function.
533
 * @param range_i     the number of items to process along the first dimension
534
 *    of the 2D grid.
535
 * @param range_j     the number of items to process along the second dimension
536
 *    of the 2D grid.
537
 * @param flags       a bitwise combination of zero or more optional flags
538
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
539
 */
540
void pthreadpool_parallelize_2d(pthreadpool_t threadpool,
541
                                pthreadpool_task_2d_t function, void* context,
542
                                size_t range_i, size_t range_j, uint32_t flags);
543
544
/**
545
 * Process items on a 2D grid passing along the current thread id.
546
 *
547
 * The function implements a parallel version of the following snippet:
548
 *
549
 *   for (size_t i = 0; i < range_i; i++)
550
 *     for (size_t j = 0; j < range_j; j++)
551
 *       function(context, thread_index, i, j);
552
 *
553
 * When the function returns, all items have been processed and the thread pool
554
 * is ready for a new task.
555
 *
556
 * @note If multiple threads call this function with the same thread pool, the
557
 *    calls are serialized.
558
 *
559
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
560
 *    is NULL, all items are processed serially on the calling thread.
561
 * @param function    the function to call for each item.
562
 * @param context     the first argument passed to the specified function.
563
 * @param range_i     the number of items to process along the first dimension
564
 *    of the 2D grid.
565
 * @param range_j     the number of items to process along the second dimension
566
 *    of the 2D grid.
567
 * @param flags       a bitwise combination of zero or more optional flags
568
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
569
 */
570
void pthreadpool_parallelize_2d_with_thread(
571
    pthreadpool_t threadpool, pthreadpool_task_2d_with_thread_t function,
572
    void* context, size_t range_i, size_t range_j, uint32_t flags);
573
574
/**
575
 * Process items on a 2D grid with the specified maximum tile size along the
576
 * last grid dimension.
577
 *
578
 * The function implements a parallel version of the following snippet:
579
 *
580
 *   for (size_t i = 0; i < range_i; i++)
581
 *     for (size_t j = 0; j < range_j; j += tile_j)
582
 *       function(context, i, j, min(range_j - j, tile_j));
583
 *
584
 * When the function returns, all items have been processed and the thread pool
585
 * is ready for a new task.
586
 *
587
 * @note If multiple threads call this function with the same thread pool, the
588
 *    calls are serialized.
589
 *
590
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
591
 *    is NULL, all items are processed serially on the calling thread.
592
 * @param function    the function to call for each tile.
593
 * @param context     the first argument passed to the specified function.
594
 * @param range_i     the number of items to process along the first dimension
595
 *    of the 2D grid.
596
 * @param range_j     the number of items to process along the second dimension
597
 *    of the 2D grid.
598
 * @param tile_j      the maximum number of items along the second dimension of
599
 *    the 2D grid to process in one function call.
600
 * @param flags       a bitwise combination of zero or more optional flags
601
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
602
 */
603
void pthreadpool_parallelize_2d_tile_1d(pthreadpool_t threadpool,
604
                                        pthreadpool_task_2d_tile_1d_t function,
605
                                        void* context, size_t range_i,
606
                                        size_t range_j, size_t tile_j,
607
                                        uint32_t flags);
608
609
/**
610
 * Process items on a 2D grid with the specified maximum tile size along the
611
 * last grid dimension using a microarchitecture-aware task function.
612
 *
613
 * The function implements a parallel version of the following snippet:
614
 *
615
 *   uint32_t uarch_index = cpuinfo_initialize() ?
616
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
617
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
618
 *   for (size_t i = 0; i < range_i; i++)
619
 *     for (size_t j = 0; j < range_j; j += tile_j)
620
 *       function(context, uarch_index, i, j, min(range_j - j, tile_j));
621
 *
622
 * When the function returns, all items have been processed and the thread pool
623
 * is ready for a new task.
624
 *
625
 * @note If multiple threads call this function with the same thread pool, the
626
 *    calls are serialized.
627
 *
628
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
629
 *    is NULL, all items are processed serially on the calling thread.
630
 * @param function    the function to call for each tile.
631
 * @param context     the first argument passed to the specified function.
632
 * @param default_uarch_index  the microarchitecture index to use when
633
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
634
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
635
 *    max_uarch_index value.
636
 * @param max_uarch_index      the maximum microarchitecture index expected by
637
 *    the specified function. If the index returned by
638
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
639
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
640
 * @param range_i     the number of items to process along the first dimension
641
 *    of the 2D grid.
642
 * @param range_j     the number of items to process along the second dimension
643
 *    of the 2D grid.
644
 * @param tile_j      the maximum number of items along the second dimension of
645
 *    the 2D grid to process in one function call.
646
 * @param flags       a bitwise combination of zero or more optional flags
647
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
648
 */
649
void pthreadpool_parallelize_2d_tile_1d_with_uarch(
650
    pthreadpool_t threadpool, pthreadpool_task_2d_tile_1d_with_id_t function,
651
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
652
    size_t range_i, size_t range_j, size_t tile_j, uint32_t flags);
653
654
/**
655
 * Process items on a 2D grid with the specified maximum tile size along the
656
 * last grid dimension using a microarchitecture-aware task function and passing
657
 * along the current thread id.
658
 *
659
 * The function implements a parallel version of the following snippet:
660
 *
661
 *   uint32_t uarch_index = cpuinfo_initialize() ?
662
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
663
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
664
 *   for (size_t i = 0; i < range_i; i++)
665
 *     for (size_t j = 0; j < range_j; j += tile_j)
666
 *       function(context, uarch_index, thread_index, i, j, min(range_j - j,
667
 * tile_j));
668
 *
669
 * When the function returns, all items have been processed and the thread pool
670
 * is ready for a new task.
671
 *
672
 * @note If multiple threads call this function with the same thread pool, the
673
 *    calls are serialized.
674
 *
675
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
676
 *    is NULL, all items are processed serially on the calling thread.
677
 * @param function    the function to call for each tile.
678
 * @param context     the first argument passed to the specified function.
679
 * @param default_uarch_index  the microarchitecture index to use when
680
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
681
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
682
 *    max_uarch_index value.
683
 * @param max_uarch_index      the maximum microarchitecture index expected by
684
 *    the specified function. If the index returned by
685
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
686
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
687
 * @param range_i     the number of items to process along the first dimension
688
 *    of the 2D grid.
689
 * @param range_j     the number of items to process along the second dimension
690
 *    of the 2D grid.
691
 * @param tile_j      the maximum number of items along the second dimension of
692
 *    the 2D grid to process in one function call.
693
 * @param flags       a bitwise combination of zero or more optional flags
694
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
695
 */
696
void pthreadpool_parallelize_2d_tile_1d_with_uarch_with_thread(
697
    pthreadpool_t threadpool,
698
    pthreadpool_task_2d_tile_1d_with_id_with_thread_t function, void* context,
699
    uint32_t default_uarch_index, uint32_t max_uarch_index, size_t range_i,
700
    size_t range_j, size_t tile_j, uint32_t flags);
701
702
/**
703
 * Process items on a 2D grid with specified prefered tile size along the
704
 * last grid dimension.
705
 *
706
 * The function repeatedly calls
707
 *
708
 *   function(context, i, j, count_j)
709
 *
710
 * in parallel where `i` is in the range `[0, range_i)`, `j` is in the range
711
 * `[0, range_j)` and a multiple of the provided @a tile_j, and `count_j` is an
712
 * integer multiple of @a tile_j unless `j + count_j == range_j`.
713
 *
714
 * The `count`s are chosen such as to minimize the number of calls to @a
715
 * function while keeping the computation load balanced across all threads.
716
 *
717
 * When the call returns, all items have been processed and the thread pool is
718
 * ready for a new task.
719
 *
720
 * @note If multiple threads call this function with the same thread pool,
721
 *    the calls are serialized.
722
 *
723
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
724
 *    is NULL, all items are processed serially on the calling thread.
725
 * @param function    the function to call for each interval of the given range.
726
 * @param context     the first argument passed to the specified function.
727
 * @param range_i       the number of items on the first dimension of the 2D
728
 *     grid to process.
729
 * @param range_j       the number of items on the second dimension of the 2D
730
 *     grid to process.
731
 * @param tile_j        the preferred multiple number of items on the second
732
 *     dimension of the 2D grid to process in each function call.
733
 * @param flags       a bitwise combination of zero or more optional flags
734
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
735
 */
736
void pthreadpool_parallelize_2d_tile_1d_dynamic(
737
    pthreadpool_t threadpool, pthreadpool_task_2d_tile_1d_dynamic_t function,
738
    void* context, size_t range_i, size_t range_j, size_t tile_j,
739
    uint32_t flags);
740
741
/**
742
 * Process items on a 2D grid with specified prefered tile size along the
743
 * last grid dimension, passing along the current thread id.
744
 *
745
 * The function repeatedly calls
746
 *
747
 *   function(context, thread_id, i, j, count_j)
748
 *
749
 * in parallel where `i` is in the range `[0, range_i)`, `j` is in the range
750
 * `[0, range_j)` and a multiple of the provided @a tile_j, and `count_j` is an
751
 * integer multiple of @a tile_j unless `j + count_j == range_j`.
752
 *
753
 * The `count`s are chosen such as to minimize the number of calls to @a
754
 * function while keeping the computation load balanced across all threads.
755
 *
756
 * When the call returns, all items have been processed and the thread pool is
757
 * ready for a new task.
758
 *
759
 * @note If multiple threads call this function with the same thread pool,
760
 *    the calls are serialized.
761
 *
762
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
763
 *    is NULL, all items are processed serially on the calling thread.
764
 * @param function    the function to call for each interval of the given range.
765
 * @param context     the first argument passed to the specified function.
766
 * @param range_i       the number of items on the first dimension of the 2D
767
 *     grid to process.
768
 * @param range_j       the number of items on the second dimension of the 2D
769
 *     grid to process.
770
 * @param tile_j        the preferred multiple number of items on the second
771
 *     dimension of the 2D grid to process in each function call.
772
 * @param flags       a bitwise combination of zero or more optional flags
773
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
774
 */
775
void pthreadpool_parallelize_2d_tile_1d_dynamic_with_thread(
776
    pthreadpool_t threadpool,
777
    pthreadpool_task_2d_tile_1d_dynamic_with_id_t function, void* context,
778
    size_t range_i, size_t range_j, size_t tile_j, uint32_t flags);
779
780
/**
781
 * Process items on a 2D grid with specified prefered tile size along the
782
 * last grid dimension, passing along the current uarch index and thread id.
783
 *
784
 * The function repeatedly calls
785
 *
786
 *   function(context, uarch_index, thread_id, i, j, count_j)
787
 *
788
 * in parallel where `i` is in the range `[0, range_i)`, `j` is in the range
789
 * `[0, range_j)` and a multiple of the provided @a tile_j, and `count_j` is an
790
 * integer multiple of @a tile_j unless `j + count_j == range_j`.
791
 *
792
 * The `count`s are chosen such as to minimize the number of calls to @a
793
 * function while keeping the computation load balanced across all threads.
794
 *
795
 * When the call returns, all items have been processed and the thread pool is
796
 * ready for a new task.
797
 *
798
 * @note If multiple threads call this function with the same thread pool,
799
 *    the calls are serialized.
800
 *
801
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
802
 *    is NULL, all items are processed serially on the calling thread.
803
 * @param function    the function to call for each interval of the given range.
804
 * @param context     the first argument passed to the specified function.
805
 * @param range_i       the number of items on the first dimension of the 2D
806
 *     grid to process.
807
 * @param range_j       the number of items on the second dimension of the 2D
808
 *     grid to process.
809
 * @param tile_j        the preferred multiple number of items on the second
810
 *     dimension of the 2D grid to process in each function call.
811
 * @param flags       a bitwise combination of zero or more optional flags
812
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
813
 */
814
void pthreadpool_parallelize_2d_tile_1d_dynamic_with_uarch_with_thread(
815
    pthreadpool_t threadpool,
816
    pthreadpool_task_2d_tile_1d_dynamic_with_id_with_thread_t function,
817
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
818
    size_t range_i, size_t range_j, size_t tile_j, uint32_t flags);
819
820
/**
821
 * Process items on a 2D grid with the specified maximum tile size along each
822
 * grid dimension.
823
 *
824
 * The function implements a parallel version of the following snippet:
825
 *
826
 *   for (size_t i = 0; i < range_i; i += tile_i)
827
 *     for (size_t j = 0; j < range_j; j += tile_j)
828
 *       function(context, i, j,
829
 *         min(range_i - i, tile_i), min(range_j - j, tile_j));
830
 *
831
 * When the function returns, all items have been processed and the thread pool
832
 * is ready for a new task.
833
 *
834
 * @note If multiple threads call this function with the same thread pool, the
835
 *    calls are serialized.
836
 *
837
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
838
 *    is NULL, all items are processed serially on the calling thread.
839
 * @param function    the function to call for each tile.
840
 * @param context     the first argument passed to the specified function.
841
 * @param range_i     the number of items to process along the first dimension
842
 *    of the 2D grid.
843
 * @param range_j     the number of items to process along the second dimension
844
 *    of the 2D grid.
845
 * @param tile_j      the maximum number of items along the first dimension of
846
 *    the 2D grid to process in one function call.
847
 * @param tile_j      the maximum number of items along the second dimension of
848
 *    the 2D grid to process in one function call.
849
 * @param flags       a bitwise combination of zero or more optional flags
850
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
851
 */
852
void pthreadpool_parallelize_2d_tile_2d(pthreadpool_t threadpool,
853
                                        pthreadpool_task_2d_tile_2d_t function,
854
                                        void* context, size_t range_i,
855
                                        size_t range_j, size_t tile_i,
856
                                        size_t tile_j, uint32_t flags);
857
858
/**
859
 * Process items on a 2D grid with specified prefered tile size along each grid
860
 * dimension.
861
 *
862
 * The function repeatedly calls
863
 *
864
 *   function(context, i, j, count_i, count_j)
865
 *
866
 * in parallel where `i` is in the range `[0, range_i)` and a multiple of the
867
 * provided @a tile_i, `j` is in the range `[0, range_j)` and a multiple of the
868
 * provided @a tile_j, and `count_i` and `count_j` are integer multiples of @a
869
 * tile__i and @a tile_j, unless `i + count_i == range_i` or `j + count_j ==
870
 * range_j`, respectivly.
871
 *
872
 * The `count`s are chosen such as to minimize the number of calls to @a
873
 * function while keeping the computation load balanced across all threads.
874
 *
875
 * When the call returns, all items have been processed and the thread pool is
876
 * ready for a new task.
877
 *
878
 * @note If multiple threads call this function with the same thread pool,
879
 *    the calls are serialized.
880
 *
881
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
882
 *                    is NULL, all items are processed serially on the calling
883
 *                    thread.
884
 * @param function    the function to call for each interval of the given range.
885
 * @param context     the first argument passed to the specified function.
886
 * @param range_i     the number of items on the first dimension of the 2D
887
 *                    grid to process.
888
 * @param range_j     the number of items on the second dimension of the 2D
889
 *                    grid to process.
890
 * @param tile_i      the preferred multiple number of items on the first
891
 *                    dimension of the 2D grid to process in each function call.
892
 * @param tile_j      the preferred multiple number of items on the second
893
 *                    dimension of the 2D grid to process in each function call.
894
 * @param flags       a bitwise combination of zero or more optional flags
895
 *                    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
896
 *                    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
897
 */
898
void pthreadpool_parallelize_2d_tile_2d_dynamic(
899
    pthreadpool_t threadpool, pthreadpool_task_2d_tile_2d_dynamic_t function,
900
    void* context, size_t range_i, size_t range_j, size_t tile_i, size_t tile_j,
901
    uint32_t flags);
902
903
/**
904
 * Process items on a 2D grid with specified prefered tile size along each grid
905
 * dimension using a microarchitecture-aware task function.
906
 *
907
 * The function repeatedly calls
908
 *
909
 *   function(context, uarch_index, i, j, count_i, count_j)
910
 *
911
 * in parallel where `i` is in the range `[0, range_i)` and a multiple of the
912
 * provided @a tile_i, `j` is in the range `[0, range_j)` and a multiple of the
913
 * provided @a tile_j, and `count_i` and `count_j` are integer multiples of @a
914
 * tile__i and @a tile_j, unless `i + count_i == range_i` or `j + count_j ==
915
 * range_j`, respectivly.
916
 *
917
 * The `count`s are chosen such as to minimize the number of calls to @a
918
 * function while keeping the computation load balanced across all threads.
919
 *
920
 * When the call returns, all items have been processed and the thread pool is
921
 * ready for a new task.
922
 *
923
 * @note If multiple threads call this function with the same thread pool,
924
 *    the calls are serialized.
925
 *
926
 * @param threadpool           the thread pool to use for parallelisation. If
927
 *                             threadpool is NULL, all items are processed
928
 *                             serially on the calling thread.
929
 * @param function             the function to call for each interval of the
930
 *                             given range.
931
 * @param context              the first argument passed to the specified
932
 *                             function.
933
 * @param default_uarch_index  the microarchitecture index to use when
934
 *                             pthreadpool is configured without cpuinfo,
935
 *                             cpuinfo initialization failed, or index returned
936
 *                             by cpuinfo_get_current_uarch_index() exceeds
937
 *                             the max_uarch_index value.
938
 * @param max_uarch_index      the maximum microarchitecture index expected
939
 *                             by the specified function. If the index returned
940
 *                             by cpuinfo_get_current_uarch_index() exceeds this
941
 *                             value, default_uarch_index will be used instead.
942
 *                             default_uarch_index can exceed max_uarch_index.
943
 * @param range_i              the number of items on the first dimension of the
944
 *                             2D grid to process.
945
 * @param range_j              the number of items on the second dimension of
946
 *                             the 2D grid to process.
947
 * @param tile_i               the preferred multiple number of items on the
948
 *                             first dimension of the 2D grid to process in each
949
 *                             function call.
950
 * @param tile_j               the preferred multiple number of items on the
951
 *                             second dimension of the 2D grid to process in
952
 *                             each function call.
953
 * @param flags                a bitwise combination of zero or more optional
954
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
955
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
956
 */
957
void pthreadpool_parallelize_2d_tile_2d_dynamic_with_uarch(
958
    pthreadpool_t threadpool,
959
    pthreadpool_task_2d_tile_2d_dynamic_with_id_t function, void* context,
960
    uint32_t default_uarch_index, uint32_t max_uarch_index, size_t range_i,
961
    size_t range_j, size_t tile_i, size_t tile_j, uint32_t flags);
962
963
/**
964
 * Process items on a 2D grid with specified prefered tile size along each grid
965
 * dimension passing along the current thread id.
966
 *
967
 * The function repeatedly calls
968
 *
969
 *   function(context, thread_id, i, j, count_i, count_j)
970
 *
971
 * in parallel where `i` is in the range `[0, range_i)` and a multiple of the
972
 * provided @a tile_i, `j` is in the range `[0, range_j)` and a multiple of the
973
 * provided @a tile_j, and `count_i` and `count_j` are integer multiples of @a
974
 * tile__i and @a tile_j, unless `i + count_i == range_i` or `j + count_j ==
975
 * range_j`, respectivly.
976
 *
977
 * The `count`s are chosen such as to minimize the number of calls to @a
978
 * function while keeping the computation load balanced across all threads.
979
 *
980
 * When the call returns, all items have been processed and the thread pool is
981
 * ready for a new task.
982
 *
983
 * @note If multiple threads call this function with the same thread pool,
984
 *    the calls are serialized.
985
 *
986
 * @param threadpool           the thread pool to use for parallelisation. If
987
 *                             threadpool is NULL, all items are processed
988
 *                             serially on the calling thread.
989
 * @param function             the function to call for each interval of the
990
 *                             given range.
991
 * @param context              the first argument passed to the specified
992
 *                             function.
993
 * @param range_i              the number of items on the first dimension of the
994
 *                             2D grid to process.
995
 * @param range_j              the number of items on the second dimension of
996
 *                             the 2D grid to process.
997
 * @param tile_i               the preferred multiple number of items on the
998
 *                             first dimension of the 2D grid to process in each
999
 *                             function call.
1000
 * @param tile_j               the preferred multiple number of items on the
1001
 *                             second dimension of the 2D grid to process in
1002
 *                             each function call.
1003
 * @param flags                a bitwise combination of zero or more optional
1004
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1005
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1006
 */
1007
void pthreadpool_parallelize_2d_tile_2d_dynamic_with_thread(
1008
    pthreadpool_t threadpool,
1009
    pthreadpool_task_2d_tile_2d_dynamic_with_id_t function, void* context,
1010
    size_t range_i, size_t range_j, size_t tile_i, size_t tile_j,
1011
    uint32_t flags);
1012
1013
/**
1014
 * Process items on a 2D grid with the specified maximum tile size along each
1015
 * grid dimension using a microarchitecture-aware task function.
1016
 *
1017
 * The function implements a parallel version of the following snippet:
1018
 *
1019
 *   uint32_t uarch_index = cpuinfo_initialize() ?
1020
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
1021
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
1022
 *   for (size_t i = 0; i < range_i; i += tile_i)
1023
 *     for (size_t j = 0; j < range_j; j += tile_j)
1024
 *       function(context, uarch_index, i, j,
1025
 *         min(range_i - i, tile_i), min(range_j - j, tile_j));
1026
 *
1027
 * When the function returns, all items have been processed and the thread pool
1028
 * is ready for a new task.
1029
 *
1030
 * @note If multiple threads call this function with the same thread pool, the
1031
 *    calls are serialized.
1032
 *
1033
 * @param threadpool           the thread pool to use for parallelisation. If
1034
 *    threadpool is NULL, all items are processed serially on the calling
1035
 *    thread.
1036
 * @param function             the function to call for each tile.
1037
 * @param context              the first argument passed to the specified
1038
 *    function.
1039
 * @param default_uarch_index  the microarchitecture index to use when
1040
 *                             pthreadpool is configured without cpuinfo,
1041
 *                             cpuinfo initialization failed, or index returned
1042
 *                             by cpuinfo_get_current_uarch_index() exceeds
1043
 *                             the max_uarch_index value.
1044
 * @param max_uarch_index      the maximum microarchitecture index expected
1045
 *                             by the specified function. If the index returned
1046
 *                             by cpuinfo_get_current_uarch_index() exceeds this
1047
 *                             value, default_uarch_index will be used instead.
1048
 *                             default_uarch_index can exceed max_uarch_index.
1049
 * @param range_i              the number of items to process along the first
1050
 *    dimension of the 2D grid.
1051
 * @param range_j              the number of items to process along the second
1052
 *    dimension of the 2D grid.
1053
 * @param tile_j               the maximum number of items along the first
1054
 *    dimension of the 2D grid to process in one function call.
1055
 * @param tile_j               the maximum number of items along the second
1056
 *    dimension of the 2D grid to process in one function call.
1057
 * @param flags                a bitwise combination of zero or more optional
1058
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1059
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1060
 */
1061
void pthreadpool_parallelize_2d_tile_2d_with_uarch(
1062
    pthreadpool_t threadpool, pthreadpool_task_2d_tile_2d_with_id_t function,
1063
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
1064
    size_t range_i, size_t range_j, size_t tile_i, size_t tile_j,
1065
    uint32_t flags);
1066
1067
/**
1068
 * Process items on a 3D grid.
1069
 *
1070
 * The function implements a parallel version of the following snippet:
1071
 *
1072
 *   for (size_t i = 0; i < range_i; i++)
1073
 *     for (size_t j = 0; j < range_j; j++)
1074
 *       for (size_t k = 0; k < range_k; k++)
1075
 *         function(context, i, j, k);
1076
 *
1077
 * When the function returns, all items have been processed and the thread pool
1078
 * is ready for a new task.
1079
 *
1080
 * @note If multiple threads call this function with the same thread pool, the
1081
 *    calls are serialized.
1082
 *
1083
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1084
 *    is NULL, all items are processed serially on the calling thread.
1085
 * @param function    the function to call for each tile.
1086
 * @param context     the first argument passed to the specified function.
1087
 * @param range_i     the number of items to process along the first dimension
1088
 *    of the 3D grid.
1089
 * @param range_j     the number of items to process along the second dimension
1090
 *    of the 3D grid.
1091
 * @param range_k     the number of items to process along the third dimension
1092
 *    of the 3D grid.
1093
 * @param flags       a bitwise combination of zero or more optional flags
1094
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1095
 */
1096
void pthreadpool_parallelize_3d(pthreadpool_t threadpool,
1097
                                pthreadpool_task_3d_t function, void* context,
1098
                                size_t range_i, size_t range_j, size_t range_k,
1099
                                uint32_t flags);
1100
1101
/**
1102
 * Process items on a 3D grid with the specified maximum tile size along the
1103
 * last grid dimension.
1104
 *
1105
 * The function implements a parallel version of the following snippet:
1106
 *
1107
 *   for (size_t i = 0; i < range_i; i++)
1108
 *     for (size_t j = 0; j < range_j; j++)
1109
 *       for (size_t k = 0; k < range_k; k += tile_k)
1110
 *         function(context, i, j, k, min(range_k - k, tile_k));
1111
 *
1112
 * When the function returns, all items have been processed and the thread pool
1113
 * is ready for a new task.
1114
 *
1115
 * @note If multiple threads call this function with the same thread pool, the
1116
 *    calls are serialized.
1117
 *
1118
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1119
 *    is NULL, all items are processed serially on the calling thread.
1120
 * @param function    the function to call for each tile.
1121
 * @param context     the first argument passed to the specified function.
1122
 * @param range_i     the number of items to process along the first dimension
1123
 *    of the 3D grid.
1124
 * @param range_j     the number of items to process along the second dimension
1125
 *    of the 3D grid.
1126
 * @param range_k     the number of items to process along the third dimension
1127
 *    of the 3D grid.
1128
 * @param tile_k      the maximum number of items along the third dimension of
1129
 *    the 3D grid to process in one function call.
1130
 * @param flags       a bitwise combination of zero or more optional flags
1131
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1132
 */
1133
void pthreadpool_parallelize_3d_tile_1d(pthreadpool_t threadpool,
1134
                                        pthreadpool_task_3d_tile_1d_t function,
1135
                                        void* context, size_t range_i,
1136
                                        size_t range_j, size_t range_k,
1137
                                        size_t tile_k, uint32_t flags);
1138
1139
/**
1140
 * Process items on a 3D grid with the specified maximum tile size along the
1141
 * last grid dimension and passing along the current thread id.
1142
 *
1143
 * The function implements a parallel version of the following snippet:
1144
 *
1145
 *   for (size_t i = 0; i < range_i; i++)
1146
 *     for (size_t j = 0; j < range_j; j++)
1147
 *       for (size_t k = 0; k < range_k; k += tile_k)
1148
 *         function(context, thread_index, i, j, k, min(range_k - k, tile_k));
1149
 *
1150
 * When the function returns, all items have been processed and the thread pool
1151
 * is ready for a new task.
1152
 *
1153
 * @note If multiple threads call this function with the same thread pool, the
1154
 *    calls are serialized.
1155
 *
1156
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1157
 *    is NULL, all items are processed serially on the calling thread.
1158
 * @param function    the function to call for each tile.
1159
 * @param context     the first argument passed to the specified function.
1160
 * @param range_i     the number of items to process along the first dimension
1161
 *    of the 3D grid.
1162
 * @param range_j     the number of items to process along the second dimension
1163
 *    of the 3D grid.
1164
 * @param range_k     the number of items to process along the third dimension
1165
 *    of the 3D grid.
1166
 * @param tile_k      the maximum number of items along the third dimension of
1167
 *    the 3D grid to process in one function call.
1168
 * @param flags       a bitwise combination of zero or more optional flags
1169
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1170
 */
1171
void pthreadpool_parallelize_3d_tile_1d_with_thread(
1172
    pthreadpool_t threadpool,
1173
    pthreadpool_task_3d_tile_1d_with_thread_t function, void* context,
1174
    size_t range_i, size_t range_j, size_t range_k, size_t tile_k,
1175
    uint32_t flags);
1176
1177
/**
1178
 * Process items on a 3D grid with the specified maximum tile size along the
1179
 * last grid dimension using a microarchitecture-aware task function.
1180
 *
1181
 * The function implements a parallel version of the following snippet:
1182
 *
1183
 *   uint32_t uarch_index = cpuinfo_initialize() ?
1184
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
1185
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
1186
 *   for (size_t i = 0; i < range_i; i++)
1187
 *     for (size_t j = 0; j < range_j; j++)
1188
 *       for (size_t k = 0; k < range_k; k += tile_k)
1189
 *         function(context, uarch_index, i, j, k, min(range_k - k, tile_k));
1190
 *
1191
 * When the function returns, all items have been processed and the thread pool
1192
 * is ready for a new task.
1193
 *
1194
 * @note If multiple threads call this function with the same thread pool, the
1195
 *    calls are serialized.
1196
 *
1197
 * @param threadpool           the thread pool to use for parallelisation. If
1198
 *    threadpool is NULL, all items are processed serially on the calling
1199
 *    thread.
1200
 * @param function             the function to call for each tile.
1201
 * @param context              the first argument passed to the specified
1202
 *    function.
1203
 * @param default_uarch_index  the microarchitecture index to use when
1204
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
1205
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
1206
 *    max_uarch_index value.
1207
 * @param max_uarch_index      the maximum microarchitecture index expected by
1208
 *    the specified function. If the index returned by
1209
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
1210
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
1211
 * @param range_i              the number of items to process along the first
1212
 *    dimension of the 3D grid.
1213
 * @param range_j              the number of items to process along the second
1214
 *    dimension of the 3D grid.
1215
 * @param range_k              the number of items to process along the third
1216
 *    dimension of the 3D grid.
1217
 * @param tile_k               the maximum number of items along the third
1218
 *    dimension of the 3D grid to process in one function call.
1219
 * @param flags                a bitwise combination of zero or more optional
1220
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1221
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1222
 */
1223
void pthreadpool_parallelize_3d_tile_1d_with_uarch(
1224
    pthreadpool_t threadpool, pthreadpool_task_3d_tile_1d_with_id_t function,
1225
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
1226
    size_t range_i, size_t range_j, size_t range_k, size_t tile_k,
1227
    uint32_t flags);
1228
1229
/**
1230
 * Process items on a 3D grid with the specified maximum tile size along the
1231
 * last grid dimension using a microarchitecture-aware task function and passing
1232
 * along the current thread id.
1233
 *
1234
 * The function implements a parallel version of the following snippet:
1235
 *
1236
 *   uint32_t uarch_index = cpuinfo_initialize() ?
1237
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
1238
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
1239
 *   for (size_t i = 0; i < range_i; i++)
1240
 *     for (size_t j = 0; j < range_j; j++)
1241
 *       for (size_t k = 0; k < range_k; k += tile_k)
1242
 *         function(context, uarch_index, thread_index, i, j, k, min(range_k -
1243
 * k, tile_k));
1244
 *
1245
 * When the function returns, all items have been processed and the thread pool
1246
 * is ready for a new task.
1247
 *
1248
 * @note If multiple threads call this function with the same thread pool, the
1249
 *    calls are serialized.
1250
 *
1251
 * @param threadpool           the thread pool to use for parallelisation. If
1252
 *    threadpool is NULL, all items are processed serially on the calling
1253
 *    thread.
1254
 * @param function             the function to call for each tile.
1255
 * @param context              the first argument passed to the specified
1256
 *    function.
1257
 * @param default_uarch_index  the microarchitecture index to use when
1258
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
1259
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
1260
 *    max_uarch_index value.
1261
 * @param max_uarch_index      the maximum microarchitecture index expected by
1262
 *    the specified function. If the index returned by
1263
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
1264
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
1265
 * @param range_i              the number of items to process along the first
1266
 *    dimension of the 3D grid.
1267
 * @param range_j              the number of items to process along the second
1268
 *    dimension of the 3D grid.
1269
 * @param range_k              the number of items to process along the third
1270
 *    dimension of the 3D grid.
1271
 * @param tile_k               the maximum number of items along the third
1272
 *    dimension of the 3D grid to process in one function call.
1273
 * @param flags                a bitwise combination of zero or more optional
1274
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1275
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1276
 */
1277
void pthreadpool_parallelize_3d_tile_1d_with_uarch_with_thread(
1278
    pthreadpool_t threadpool,
1279
    pthreadpool_task_3d_tile_1d_with_id_with_thread_t function, void* context,
1280
    uint32_t default_uarch_index, uint32_t max_uarch_index, size_t range_i,
1281
    size_t range_j, size_t range_k, size_t tile_k, uint32_t flags);
1282
1283
/**
1284
 * Process items on a 3D grid with specified prefered tile size along the last
1285
 * grid dimension.
1286
 *
1287
 * The function repeatedly calls
1288
 *
1289
 *   function(context, i, j, k, count_k)
1290
 *
1291
 * in parallel where:
1292
 *  - `i` is in the range `[0, range_i)`,
1293
 *  - `j` is in the range `[0, range_j)`,
1294
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1295
 *    tile_k,
1296
 *  - `count_k` is an integer multiple of @a tile_k, unless `k + count_k ==
1297
 *    range_k`.
1298
 *
1299
 * The `count`s are chosen such as to minimize the number of calls to @a
1300
 * function while keeping the computation load balanced across all threads.
1301
 *
1302
 * When the call returns, all items have been processed and the thread pool is
1303
 * ready for a new task.
1304
 *
1305
 * @note If multiple threads call this function with the same thread pool,
1306
 *    the calls are serialized.
1307
 *
1308
 * @param threadpool           the thread pool to use for parallelisation. If
1309
 *                             threadpool is NULL, all items are processed
1310
 *                             serially on the calling thread.
1311
 * @param function             the function to call for each interval of the
1312
 *                             given range.
1313
 * @param context              the first argument passed to the specified
1314
 *                             function.
1315
 * @param range_i              the number of items on the first dimension of the
1316
 *                             3D grid to process.
1317
 * @param range_j              the number of items on the second dimension of
1318
 *                             the 3D grid to process.
1319
 * @param range_k              the number of items on the third dimension of the
1320
 *                             3D grid to process.
1321
 * @param tile_k               the preferred multiple number of items on the
1322
 *                             third dimension of the 3D grid to process in each
1323
 *                             function call.
1324
 * @param flags                a bitwise combination of zero or more optional
1325
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1326
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1327
 */
1328
void pthreadpool_parallelize_3d_tile_1d_dynamic(
1329
    pthreadpool_t threadpool,
1330
    pthreadpool_task_3d_tile_1d_dynamic_t function, void* context,
1331
    size_t range_i, size_t range_j, size_t range_k, size_t tile_k,
1332
    uint32_t flags);
1333
1334
/**
1335
 * Process items on a 3D grid with specified prefered tile size along the last
1336
 * grid dimension, passing along the thread ID.
1337
 *
1338
 * The function repeatedly calls
1339
 *
1340
 *   function(context, thread_id, i, j, k, count_k)
1341
 *
1342
 * in parallel where:
1343
 *  - `i` is in the range `[0, range_i)`,
1344
 *  - `j` is in the range `[0, range_j)`,
1345
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1346
 *    tile_k,
1347
 *  - `count_k` is an integer multiple of @a tile_k, unless `k + count_k ==
1348
 *    range_k`.
1349
 *
1350
 * The `count`s are chosen such as to minimize the number of calls to @a
1351
 * function while keeping the computation load balanced across all threads.
1352
 *
1353
 * When the call returns, all items have been processed and the thread pool is
1354
 * ready for a new task.
1355
 *
1356
 * @note If multiple threads call this function with the same thread pool,
1357
 *    the calls are serialized.
1358
 *
1359
 * @param threadpool           the thread pool to use for parallelisation. If
1360
 *                             threadpool is NULL, all items are processed
1361
 *                             serially on the calling thread.
1362
 * @param function             the function to call for each interval of the
1363
 *                             given range.
1364
 * @param context              the first argument passed to the specified
1365
 *                             function.
1366
 * @param range_i              the number of items on the first dimension of the
1367
 *                             3D grid to process.
1368
 * @param range_j              the number of items on the second dimension of
1369
 *                             the 3D grid to process.
1370
 * @param range_k              the number of items on the third dimension of the
1371
 *                             3D grid to process.
1372
 * @param tile_k               the preferred multiple number of items on the
1373
 *                             third dimension of the 3D grid to process in each
1374
 *                             function call.
1375
 * @param flags                a bitwise combination of zero or more optional
1376
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1377
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1378
 */
1379
void pthreadpool_parallelize_3d_tile_1d_dynamic_with_thread(
1380
    pthreadpool_t threadpool,
1381
    pthreadpool_task_3d_tile_1d_dynamic_with_id_t function, void* context,
1382
    size_t range_i, size_t range_j, size_t range_k, size_t tile_k,
1383
    uint32_t flags);
1384
1385
/**
1386
 * Process items on a 3D grid with specified prefered tile size along the last
1387
 * grid dimension, passing along the thread ID.
1388
 *
1389
 * The function repeatedly calls
1390
 *
1391
 *   function(context, uarch_index, thread_index, i, j, k, count_k)
1392
 *
1393
 * in parallel where:
1394
 *  - `i` is in the range `[0, range_i)`,
1395
 *  - `j` is in the range `[0, range_j)`,
1396
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1397
 *    tile_k,
1398
 *  - `count_k` is an integer multiple of @a tile_k, unless `k + count_k ==
1399
 *    range_k`.
1400
 *
1401
 * The `count`s are chosen such as to minimize the number of calls to @a
1402
 * function while keeping the computation load balanced across all threads.
1403
 *
1404
 * When the call returns, all items have been processed and the thread pool is
1405
 * ready for a new task.
1406
 *
1407
 * @note If multiple threads call this function with the same thread pool,
1408
 *    the calls are serialized.
1409
 *
1410
 * @param threadpool           the thread pool to use for parallelisation. If
1411
 *                             threadpool is NULL, all items are processed
1412
 *                             serially on the calling thread.
1413
 * @param function             the function to call for each interval of the
1414
 *                             given range.
1415
 * @param context              the first argument passed to the specified
1416
 *                             function.
1417
 * @param default_uarch_index  the microarchitecture index to use when
1418
 *                             pthreadpool is configured without cpuinfo,
1419
 *                             cpuinfo initialization failed, or index returned
1420
 *                             by cpuinfo_get_current_uarch_index() exceeds the
1421
 *                             max_uarch_index value.
1422
 * @param max_uarch_index      the maximum microarchitecture index expected by
1423
 *                             the specified function. If the index returned by
1424
 *                             cpuinfo_get_current_uarch_index() exceeds this
1425
 *                             value, default_uarch_index will be used instead.
1426
 *                             default_uarch_index can exceed max_uarch_index.
1427
 * @param range_i              the number of items on the first dimension of the
1428
 *                             3D grid to process.
1429
 * @param range_j              the number of items on the second dimension of
1430
 *                             the 3D grid to process.
1431
 * @param range_k              the number of items on the third dimension of the
1432
 *                             3D grid to process.
1433
 * @param tile_k               the preferred multiple number of items on the
1434
 *                             third dimension of the 3D grid to process in each
1435
 *                             function call.
1436
 * @param flags                a bitwise combination of zero or more optional
1437
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1438
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1439
 */
1440
void pthreadpool_parallelize_3d_tile_1d_dynamic_with_uarch_with_thread(
1441
    pthreadpool_t threadpool,
1442
    pthreadpool_task_3d_tile_1d_dynamic_with_id_with_thread_t function,
1443
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
1444
    size_t range_i, size_t range_j, size_t range_k, size_t tile_k,
1445
    uint32_t flags);
1446
1447
/**
1448
 * Process items on a 3D grid with the specified maximum tile size along the
1449
 * last two grid dimensions.
1450
 *
1451
 * The function implements a parallel version of the following snippet:
1452
 *
1453
 *   for (size_t i = 0; i < range_i; i++)
1454
 *     for (size_t j = 0; j < range_j; j += tile_j)
1455
 *       for (size_t k = 0; k < range_k; k += tile_k)
1456
 *         function(context, i, j, k,
1457
 *           min(range_j - j, tile_j), min(range_k - k, tile_k));
1458
 *
1459
 * When the function returns, all items have been processed and the thread pool
1460
 * is ready for a new task.
1461
 *
1462
 * @note If multiple threads call this function with the same thread pool, the
1463
 *    calls are serialized.
1464
 *
1465
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1466
 *    is NULL, all items are processed serially on the calling thread.
1467
 * @param function    the function to call for each tile.
1468
 * @param context     the first argument passed to the specified function.
1469
 * @param range_i     the number of items to process along the first dimension
1470
 *    of the 3D grid.
1471
 * @param range_j     the number of items to process along the second dimension
1472
 *    of the 3D grid.
1473
 * @param range_k     the number of items to process along the third dimension
1474
 *    of the 3D grid.
1475
 * @param tile_j      the maximum number of items along the second dimension of
1476
 *    the 3D grid to process in one function call.
1477
 * @param tile_k      the maximum number of items along the third dimension of
1478
 *    the 3D grid to process in one function call.
1479
 * @param flags       a bitwise combination of zero or more optional flags
1480
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1481
 */
1482
void pthreadpool_parallelize_3d_tile_2d(pthreadpool_t threadpool,
1483
                                        pthreadpool_task_3d_tile_2d_t function,
1484
                                        void* context, size_t range_i,
1485
                                        size_t range_j, size_t range_k,
1486
                                        size_t tile_j, size_t tile_k,
1487
                                        uint32_t flags);
1488
1489
/**
1490
 * Process items on a 3D grid with specified prefered tile size along the last
1491
 * two grid dimensions.
1492
 *
1493
 * The function repeatedly calls
1494
 *
1495
 *   function(context, i, j, k, count_j, count_k)
1496
 *
1497
 * in parallel where:
1498
 *  - `i` is in the range `[0, range_i)`,
1499
 *  - `j` is in the range `[0, range_j)` and a multiple of the provided @a
1500
 *    tile_j,
1501
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1502
 *    tile_k,
1503
 *  - `count_j` and `count_k` are integer multiples of @a tile__j and @a tile_k,
1504
 *    unless `j + count_j == range_j` or `k + count_k == range_k`, respectivly.
1505
 *
1506
 * The `count`s are chosen such as to minimize the number of calls to @a
1507
 * function while keeping the computation load balanced across all threads.
1508
 *
1509
 * When the call returns, all items have been processed and the thread pool is
1510
 * ready for a new task.
1511
 *
1512
 * @note If multiple threads call this function with the same thread pool,
1513
 *    the calls are serialized.
1514
 *
1515
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1516
 *                    is NULL, all items are processed serially on the calling
1517
 *                    thread.
1518
 * @param function    the function to call for each interval of the given range.
1519
 * @param context     the first argument passed to the specified function.
1520
 * @param range_i     the number of items on the first dimension of the 3D
1521
 *                    grid to process.
1522
 * @param range_j     the number of items on the second dimension of the 3D
1523
 *                    grid to process.
1524
 * @param range_k     the number of items on the third dimension of the 3D
1525
 *                    grid to process.
1526
 * @param tile_j      the preferred multiple number of items on the second
1527
 *                    dimension of the 3D grid to process in each function call.
1528
 * @param tile_k      the preferred multiple number of items on the third
1529
 *                    dimension of the 3D grid to process in each function call.
1530
 * @param flags       a bitwise combination of zero or more optional flags
1531
 *                    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1532
 *                    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1533
 */
1534
void pthreadpool_parallelize_3d_tile_2d_dynamic(
1535
    pthreadpool_t threadpool, pthreadpool_task_3d_tile_2d_dynamic_t function,
1536
    void* context, size_t range_i, size_t range_j, size_t range_k,
1537
    size_t tile_j, size_t tile_k, uint32_t flags);
1538
1539
/**
1540
 * Process items on a 3D grid with specified prefered tile size along the last
1541
 * two grid dimensions using a microarchitecture-aware task function.
1542
 *
1543
 * The function repeatedly calls
1544
 *
1545
 *   function(context, uarch_index, i, j, k, count_j, count_k)
1546
 *
1547
 * in parallel where:
1548
 *  - `i` is in the range `[0, range_i)`,
1549
 *  - `j` is in the range `[0, range_j)` and a multiple of the provided @a
1550
 *    tile_j,
1551
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1552
 *    tile_k,
1553
 *  - `count_j` and `count_k` are integer multiples of @a tile__j and @a tile_k,
1554
 *    unless `j + count_j == range_j` or `k + count_k == range_k`, respectivly.
1555
 *
1556
 * The `count`s are chosen such as to minimize the number of calls to @a
1557
 * function while keeping the computation load balanced across all threads.
1558
 *
1559
 * When the call returns, all items have been processed and the thread pool is
1560
 * ready for a new task.
1561
 *
1562
 * @note If multiple threads call this function with the same thread pool,
1563
 *    the calls are serialized.
1564
 *
1565
 * @param threadpool           the thread pool to use for parallelisation. If
1566
 *                             threadpool is NULL, all items are processed
1567
 *                             serially on the calling thread.
1568
 * @param function             the function to call for each interval of the
1569
 *                             given range.
1570
 * @param context              the first argument passed to the specified
1571
 *                             function.
1572
 * @param default_uarch_index  the microarchitecture index to use when
1573
 *                             pthreadpool is configured without cpuinfo,
1574
 *                             cpuinfo initialization failed, or index returned
1575
 *                             by cpuinfo_get_current_uarch_index() exceeds
1576
 *                             the max_uarch_index value.
1577
 * @param max_uarch_index      the maximum microarchitecture index expected
1578
 *                             by the specified function. If the index returned
1579
 *                             by cpuinfo_get_current_uarch_index() exceeds this
1580
 *                             value, default_uarch_index will be used instead.
1581
 *                             default_uarch_index can exceed max_uarch_index.
1582
 * @param range_i              the number of items on the first dimension of the
1583
 *                             3D grid to process.
1584
 * @param range_j              the number of items on the second dimension of
1585
 *                             the 3D grid to process.
1586
 * @param range_k              the number of items on the third dimension of the
1587
 *                             3D grid to process.
1588
 * @param tile_j               the preferred multiple number of items on the
1589
 *                             second dimension of the 3D grid to process in
1590
 *                             each function call.
1591
 * @param tile_k               the preferred multiple number of items on the
1592
 *                             third dimension of the 3D grid to process in each
1593
 *                             function call.
1594
 * @param flags                a bitwise combination of zero or more optional
1595
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1596
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1597
 */
1598
void pthreadpool_parallelize_3d_tile_2d_dynamic_with_uarch(
1599
    pthreadpool_t threadpool,
1600
    pthreadpool_task_3d_tile_2d_dynamic_with_id_t function, void* context,
1601
    uint32_t default_uarch_index, uint32_t max_uarch_index, size_t range_i,
1602
    size_t range_j, size_t range_k, size_t tile_j, size_t tile_k,
1603
    uint32_t flags);
1604
1605
/**
1606
 * Process items on a 3D grid with specified prefered tile size along the last
1607
 * two grid dimensions passing along the thread ID.
1608
 *
1609
 * The function repeatedly calls
1610
 *
1611
 *   function(context, thread_id, i, j, k, count_j, count_k)
1612
 *
1613
 * in parallel where:
1614
 *  - `i` is in the range `[0, range_i)`,
1615
 *  - `j` is in the range `[0, range_j)` and a multiple of the provided @a
1616
 *    tile_j,
1617
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1618
 *    tile_k,
1619
 *  - `count_j` and `count_k` are integer multiples of @a tile__j and @a tile_k,
1620
 *    unless `j + count_j == range_j` or `k + count_k == range_k`, respectivly.
1621
 *
1622
 * The `count`s are chosen such as to minimize the number of calls to @a
1623
 * function while keeping the computation load balanced across all threads.
1624
 *
1625
 * When the call returns, all items have been processed and the thread pool is
1626
 * ready for a new task.
1627
 *
1628
 * @note If multiple threads call this function with the same thread pool,
1629
 *    the calls are serialized.
1630
 *
1631
 * @param threadpool           the thread pool to use for parallelisation. If
1632
 *                             threadpool is NULL, all items are processed
1633
 *                             serially on the calling thread.
1634
 * @param function             the function to call for each interval of the
1635
 *                             given range.
1636
 * @param context              the first argument passed to the specified
1637
 *                             function.
1638
 * @param range_i              the number of items on the first dimension of the
1639
 *                             3D grid to process.
1640
 * @param range_j              the number of items on the second dimension of
1641
 *                             the 3D grid to process.
1642
 * @param range_k              the number of items on the third dimension of the
1643
 *                             3D grid to process.
1644
 * @param tile_j               the preferred multiple number of items on the
1645
 *                             second dimension of the 3D grid to process in
1646
 *                             each function call.
1647
 * @param tile_k               the preferred multiple number of items on the
1648
 *                             third dimension of the 3D grid to process in each
1649
 *                             function call.
1650
 * @param flags                a bitwise combination of zero or more optional
1651
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1652
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1653
 */
1654
void pthreadpool_parallelize_3d_tile_2d_dynamic_with_thread(
1655
    pthreadpool_t threadpool,
1656
    pthreadpool_task_3d_tile_2d_dynamic_with_id_t function, void* context,
1657
    size_t range_i, size_t range_j, size_t range_k, size_t tile_j,
1658
    size_t tile_k, uint32_t flags);
1659
1660
/**
1661
 * Process items on a 3D grid with the specified maximum tile size along the
1662
 * last two grid dimensions using a microarchitecture-aware task function.
1663
 *
1664
 * The function implements a parallel version of the following snippet:
1665
 *
1666
 *   uint32_t uarch_index = cpuinfo_initialize() ?
1667
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
1668
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
1669
 *   for (size_t i = 0; i < range_i; i++)
1670
 *     for (size_t j = 0; j < range_j; j += tile_j)
1671
 *       for (size_t k = 0; k < range_k; k += tile_k)
1672
 *         function(context, uarch_index, i, j, k,
1673
 *           min(range_j - j, tile_j), min(range_k - k, tile_k));
1674
 *
1675
 * When the function returns, all items have been processed and the thread pool
1676
 * is ready for a new task.
1677
 *
1678
 * @note If multiple threads call this function with the same thread pool, the
1679
 *    calls are serialized.
1680
 *
1681
 * @param threadpool           the thread pool to use for parallelisation. If
1682
 *    threadpool is NULL, all items are processed serially on the calling
1683
 *    thread.
1684
 * @param function             the function to call for each tile.
1685
 * @param context              the first argument passed to the specified
1686
 *    function.
1687
 * @param default_uarch_index  the microarchitecture index to use when
1688
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
1689
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
1690
 *    max_uarch_index value.
1691
 * @param max_uarch_index      the maximum microarchitecture index expected by
1692
 *    the specified function. If the index returned by
1693
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
1694
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
1695
 * @param range_i              the number of items to process along the first
1696
 *    dimension of the 3D grid.
1697
 * @param range_j              the number of items to process along the second
1698
 *    dimension of the 3D grid.
1699
 * @param range_k              the number of items to process along the third
1700
 *    dimension of the 3D grid.
1701
 * @param tile_j               the maximum number of items along the second
1702
 *    dimension of the 3D grid to process in one function call.
1703
 * @param tile_k               the maximum number of items along the third
1704
 *    dimension of the 3D grid to process in one function call.
1705
 * @param flags                a bitwise combination of zero or more optional
1706
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1707
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1708
 */
1709
void pthreadpool_parallelize_3d_tile_2d_with_uarch(
1710
    pthreadpool_t threadpool, pthreadpool_task_3d_tile_2d_with_id_t function,
1711
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
1712
    size_t range_i, size_t range_j, size_t range_k, size_t tile_j,
1713
    size_t tile_k, uint32_t flags);
1714
1715
/**
1716
 * Process items on a 4D grid.
1717
 *
1718
 * The function implements a parallel version of the following snippet:
1719
 *
1720
 *   for (size_t i = 0; i < range_i; i++)
1721
 *     for (size_t j = 0; j < range_j; j++)
1722
 *       for (size_t k = 0; k < range_k; k++)
1723
 *         for (size_t l = 0; l < range_l; l++)
1724
 *           function(context, i, j, k, l);
1725
 *
1726
 * When the function returns, all items have been processed and the thread pool
1727
 * is ready for a new task.
1728
 *
1729
 * @note If multiple threads call this function with the same thread pool, the
1730
 *    calls are serialized.
1731
 *
1732
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1733
 *    is NULL, all items are processed serially on the calling thread.
1734
 * @param function    the function to call for each tile.
1735
 * @param context     the first argument passed to the specified function.
1736
 * @param range_i     the number of items to process along the first dimension
1737
 *    of the 4D grid.
1738
 * @param range_j     the number of items to process along the second dimension
1739
 *    of the 4D grid.
1740
 * @param range_k     the number of items to process along the third dimension
1741
 *    of the 4D grid.
1742
 * @param range_l     the number of items to process along the fourth dimension
1743
 *    of the 4D grid.
1744
 * @param flags       a bitwise combination of zero or more optional flags
1745
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1746
 */
1747
void pthreadpool_parallelize_4d(pthreadpool_t threadpool,
1748
                                pthreadpool_task_4d_t function, void* context,
1749
                                size_t range_i, size_t range_j, size_t range_k,
1750
                                size_t range_l, uint32_t flags);
1751
1752
/**
1753
 * Process items on a 4D grid with the specified maximum tile size along the
1754
 * last grid dimension.
1755
 *
1756
 * The function implements a parallel version of the following snippet:
1757
 *
1758
 *   for (size_t i = 0; i < range_i; i++)
1759
 *     for (size_t j = 0; j < range_j; j++)
1760
 *       for (size_t k = 0; k < range_k; k++)
1761
 *         for (size_t l = 0; l < range_l; l += tile_l)
1762
 *           function(context, i, j, k, l, min(range_l - l, tile_l));
1763
 *
1764
 * When the function returns, all items have been processed and the thread pool
1765
 * is ready for a new task.
1766
 *
1767
 * @note If multiple threads call this function with the same thread pool, the
1768
 *    calls are serialized.
1769
 *
1770
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1771
 *    is NULL, all items are processed serially on the calling thread.
1772
 * @param function    the function to call for each tile.
1773
 * @param context     the first argument passed to the specified function.
1774
 * @param range_i     the number of items to process along the first dimension
1775
 *    of the 4D grid.
1776
 * @param range_j     the number of items to process along the second dimension
1777
 *    of the 4D grid.
1778
 * @param range_k     the number of items to process along the third dimension
1779
 *    of the 4D grid.
1780
 * @param range_l     the number of items to process along the fourth dimension
1781
 *    of the 4D grid.
1782
 * @param tile_l      the maximum number of items along the fourth dimension of
1783
 *    the 4D grid to process in one function call.
1784
 * @param flags       a bitwise combination of zero or more optional flags
1785
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1786
 */
1787
void pthreadpool_parallelize_4d_tile_1d(pthreadpool_t threadpool,
1788
                                        pthreadpool_task_4d_tile_1d_t function,
1789
                                        void* context, size_t range_i,
1790
                                        size_t range_j, size_t range_k,
1791
                                        size_t range_l, size_t tile_l,
1792
                                        uint32_t flags);
1793
1794
/**
1795
 * Process items on a 4D grid with the specified maximum tile size along the
1796
 * last two grid dimensions.
1797
 *
1798
 * The function implements a parallel version of the following snippet:
1799
 *
1800
 *   for (size_t i = 0; i < range_i; i++)
1801
 *     for (size_t j = 0; j < range_j; j++)
1802
 *       for (size_t k = 0; k < range_k; k += tile_k)
1803
 *         for (size_t l = 0; l < range_l; l += tile_l)
1804
 *           function(context, i, j, k, l,
1805
 *             min(range_k - k, tile_k), min(range_l - l, tile_l));
1806
 *
1807
 * When the function returns, all items have been processed and the thread pool
1808
 * is ready for a new task.
1809
 *
1810
 * @note If multiple threads call this function with the same thread pool, the
1811
 *    calls are serialized.
1812
 *
1813
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1814
 *    is NULL, all items are processed serially on the calling thread.
1815
 * @param function    the function to call for each tile.
1816
 * @param context     the first argument passed to the specified function.
1817
 * @param range_i     the number of items to process along the first dimension
1818
 *    of the 4D grid.
1819
 * @param range_j     the number of items to process along the second dimension
1820
 *    of the 4D grid.
1821
 * @param range_k     the number of items to process along the third dimension
1822
 *    of the 4D grid.
1823
 * @param range_l     the number of items to process along the fourth dimension
1824
 *    of the 4D grid.
1825
 * @param tile_k      the maximum number of items along the third dimension of
1826
 *    the 4D grid to process in one function call.
1827
 * @param tile_l      the maximum number of items along the fourth dimension of
1828
 *    the 4D grid to process in one function call.
1829
 * @param flags       a bitwise combination of zero or more optional flags
1830
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1831
 */
1832
void pthreadpool_parallelize_4d_tile_2d(pthreadpool_t threadpool,
1833
                                        pthreadpool_task_4d_tile_2d_t function,
1834
                                        void* context, size_t range_i,
1835
                                        size_t range_j, size_t range_k,
1836
                                        size_t range_l, size_t tile_k,
1837
                                        size_t tile_l, uint32_t flags);
1838
1839
/**
1840
 * Process items on a 4D grid with the specified maximum tile size along the
1841
 * last two grid dimensions using a microarchitecture-aware task function.
1842
 *
1843
 * The function implements a parallel version of the following snippet:
1844
 *
1845
 *   uint32_t uarch_index = cpuinfo_initialize() ?
1846
 *       cpuinfo_get_current_uarch_index() : default_uarch_index;
1847
 *   if (uarch_index > max_uarch_index) uarch_index = default_uarch_index;
1848
 *   for (size_t i = 0; i < range_i; i++)
1849
 *     for (size_t j = 0; j < range_j; j++)
1850
 *       for (size_t k = 0; k < range_k; k += tile_k)
1851
 *         for (size_t l = 0; l < range_l; l += tile_l)
1852
 *           function(context, uarch_index, i, j, k, l,
1853
 *             min(range_k - k, tile_k), min(range_l - l, tile_l));
1854
 *
1855
 * When the function returns, all items have been processed and the thread pool
1856
 * is ready for a new task.
1857
 *
1858
 * @note If multiple threads call this function with the same thread pool, the
1859
 *    calls are serialized.
1860
 *
1861
 * @param threadpool           the thread pool to use for parallelisation. If
1862
 *    threadpool is NULL, all items are processed serially on the calling
1863
 *    thread.
1864
 * @param function             the function to call for each tile.
1865
 * @param context              the first argument passed to the specified
1866
 *    function.
1867
 * @param default_uarch_index  the microarchitecture index to use when
1868
 *    pthreadpool is configured without cpuinfo, cpuinfo initialization failed,
1869
 *    or index returned by cpuinfo_get_current_uarch_index() exceeds the
1870
 *    max_uarch_index value.
1871
 * @param max_uarch_index      the maximum microarchitecture index expected by
1872
 *    the specified function. If the index returned by
1873
 *    cpuinfo_get_current_uarch_index() exceeds this value, default_uarch_index
1874
 *    will be used instead. default_uarch_index can exceed max_uarch_index.
1875
 * @param range_i              the number of items to process along the first
1876
 *    dimension of the 4D grid.
1877
 * @param range_j              the number of items to process along the second
1878
 *    dimension of the 4D grid.
1879
 * @param range_k              the number of items to process along the third
1880
 *    dimension of the 4D grid.
1881
 * @param range_l              the number of items to process along the fourth
1882
 *    dimension of the 4D grid.
1883
 * @param tile_k               the maximum number of items along the third
1884
 *    dimension of the 4D grid to process in one function call.
1885
 * @param tile_l               the maximum number of items along the fourth
1886
 *    dimension of the 4D grid to process in one function call.
1887
 * @param flags                a bitwise combination of zero or more optional
1888
 *    flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1889
 *    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1890
 */
1891
void pthreadpool_parallelize_4d_tile_2d_with_uarch(
1892
    pthreadpool_t threadpool, pthreadpool_task_4d_tile_2d_with_id_t function,
1893
    void* context, uint32_t default_uarch_index, uint32_t max_uarch_index,
1894
    size_t range_i, size_t range_j, size_t range_k, size_t range_l,
1895
    size_t tile_k, size_t tile_l, uint32_t flags);
1896
1897
/**
1898
 * Process items on a 4D grid with specified prefered tile size along the last
1899
 * two grid dimensions.
1900
 *
1901
 * The function repeatedly calls
1902
 *
1903
 *   function(context, i, j, k, l, count_k, count_l)
1904
 *
1905
 * in parallel where:
1906
 *  - `i` is in the range `[0, range_i)`,
1907
 *  - `j` is in the range `[0, range_j)`,
1908
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1909
 *    tile_k,
1910
 *  - `l` is in the range `[0, range_l)` and a multiple of the provided @a
1911
 *    tile_l,
1912
 *  - `count_k` and `count_l` are integer multiples of @a tile_k and @a tile_l,
1913
 *    unless `k + count_k == range_k` or `l + count_l == range_l`, respectivly.
1914
 *
1915
 * The `count`s are chosen such as to minimize the number of calls to @a
1916
 * function while keeping the computation load balanced across all threads.
1917
 *
1918
 * When the call returns, all items have been processed and the thread pool is
1919
 * ready for a new task.
1920
 *
1921
 * @note If multiple threads call this function with the same thread pool,
1922
 *    the calls are serialized.
1923
 *
1924
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
1925
 *                    is NULL, all items are processed serially on the calling
1926
 *                    thread.
1927
 * @param function    the function to call for each interval of the given range.
1928
 * @param context     the first argument passed to the specified function.
1929
 * @param range_i     the number of items on the first dimension of the 4D
1930
 *                    grid to process.
1931
 * @param range_j     the number of items on the second dimension of the 4D
1932
 *                    grid to process.
1933
 * @param range_k     the number of items on the third dimension of the 4D
1934
 *                    grid to process.
1935
 * @param range_l     the number of items on the fourth dimension of the 4D
1936
 *                    grid to process.
1937
 * @param tile_k      the preferred multiple number of items on the third
1938
 *                    dimension of the 4D grid to process in each function call.
1939
 * @param tile_l      the preferred multiple number of items on the fourth
1940
 *                    dimension of the 4D grid to process in each function call.
1941
 * @param flags       a bitwise combination of zero or more optional flags
1942
 *                    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
1943
 *                    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
1944
 */
1945
void pthreadpool_parallelize_4d_tile_2d_dynamic(
1946
    pthreadpool_t threadpool, pthreadpool_task_4d_tile_2d_dynamic_t function,
1947
    void* context, size_t range_i, size_t range_j, size_t range_k,
1948
    size_t range_l, size_t tile_k, size_t tile_l, uint32_t flags);
1949
1950
/**
1951
 * Process items on a 4D grid with specified prefered tile size along the last
1952
 * two grid dimensions using a microarchitecture-aware task function.
1953
 *
1954
 * The function repeatedly calls
1955
 *
1956
 *   function(context, uarch_index, i, j, k, l, count_k, count_l)
1957
 *
1958
 * in parallel where:
1959
 *  - `i` is in the range `[0, range_i)`,
1960
 *  - `j` is in the range `[0, range_j)`,
1961
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
1962
 *    tile_k,
1963
 *  - `l` is in the range `[0, range_l)` and a multiple of the provided @a
1964
 *    tile_l,
1965
 *  - `count_k` and `count_l` are integer multiples of @a tile_k and @a tile_l,
1966
 *    unless `k + count_k == range_k` or `l + count_l == range_l`, respectivly.
1967
 *
1968
 * The `count`s are chosen such as to minimize the number of calls to @a
1969
 * function while keeping the computation load balanced across all threads.
1970
 *
1971
 * When the call returns, all items have been processed and the thread pool is
1972
 * ready for a new task.
1973
 *
1974
 * @note If multiple threads call this function with the same thread pool,
1975
 *    the calls are serialized.
1976
 *
1977
 * @param threadpool           the thread pool to use for parallelisation. If
1978
 *                             threadpool is NULL, all items are processed
1979
 *                             serially on the calling thread.
1980
 * @param function             the function to call for each interval of the
1981
 *                             given range.
1982
 * @param context              the first argument passed to the specified
1983
 *                             function.
1984
 * @param default_uarch_index  the microarchitecture index to use when
1985
 *                             pthreadpool is configured without cpuinfo,
1986
 *                             cpuinfo initialization failed, or index returned
1987
 *                             by cpuinfo_get_current_uarch_index() exceeds
1988
 *                             the max_uarch_index value.
1989
 * @param max_uarch_index      the maximum microarchitecture index expected
1990
 *                             by the specified function. If the index returned
1991
 *                             by cpuinfo_get_current_uarch_index() exceeds this
1992
 *                             value, default_uarch_index will be used instead.
1993
 *                             default_uarch_index can exceed max_uarch_index.
1994
 * @param range_i              the number of items on the first dimension of the
1995
 *                             4D grid to process.
1996
 * @param range_j              the number of items on the second dimension of
1997
 *                             the 4D grid to process.
1998
 * @param range_k              the number of items on the third dimension of the
1999
 *                             4D grid to process.
2000
 * @param range_l              the number of items on the fourth dimension of
2001
 *                             the 4D grid to process.
2002
 * @param tile_k               the preferred multiple number of items on the
2003
 *                             third dimension of the 4D grid to process in each
2004
 *                             function call.
2005
 * @param tile_l               the preferred multiple number of items on the
2006
 *                             fourth dimension of the 4D grid to process in
2007
 *                             each function call.
2008
 * @param flags                a bitwise combination of zero or more optional
2009
 *                             flags (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
2010
 *                             PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2011
 */
2012
void pthreadpool_parallelize_4d_tile_2d_dynamic_with_uarch(
2013
    pthreadpool_t threadpool,
2014
    pthreadpool_task_4d_tile_2d_dynamic_with_id_t function, void* context,
2015
    uint32_t default_uarch_index, uint32_t max_uarch_index, size_t range_i,
2016
    size_t range_j, size_t range_k, size_t range_l, size_t tile_k,
2017
    size_t tile_l, uint32_t flags);
2018
2019
/**
2020
 * Process items on a 5D grid.
2021
 *
2022
 * The function implements a parallel version of the following snippet:
2023
 *
2024
 *   for (size_t i = 0; i < range_i; i++)
2025
 *     for (size_t j = 0; j < range_j; j++)
2026
 *       for (size_t k = 0; k < range_k; k++)
2027
 *         for (size_t l = 0; l < range_l; l++)
2028
 *           for (size_t m = 0; m < range_m; m++)
2029
 *             function(context, i, j, k, l, m);
2030
 *
2031
 * When the function returns, all items have been processed and the thread pool
2032
 * is ready for a new task.
2033
 *
2034
 * @note If multiple threads call this function with the same thread pool, the
2035
 *    calls are serialized.
2036
 *
2037
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2038
 *    is NULL, all items are processed serially on the calling thread.
2039
 * @param function    the function to call for each tile.
2040
 * @param context     the first argument passed to the specified function.
2041
 * @param range_i     the number of items to process along the first dimension
2042
 *    of the 5D grid.
2043
 * @param range_j     the number of items to process along the second dimension
2044
 *    of the 5D grid.
2045
 * @param range_k     the number of items to process along the third dimension
2046
 *    of the 5D grid.
2047
 * @param range_l     the number of items to process along the fourth dimension
2048
 *    of the 5D grid.
2049
 * @param range_m     the number of items to process along the fifth dimension
2050
 *    of the 5D grid.
2051
 * @param flags       a bitwise combination of zero or more optional flags
2052
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2053
 */
2054
void pthreadpool_parallelize_5d(pthreadpool_t threadpool,
2055
                                pthreadpool_task_5d_t function, void* context,
2056
                                size_t range_i, size_t range_j, size_t range_k,
2057
                                size_t range_l, size_t range_m, uint32_t flags);
2058
2059
/**
2060
 * Process items on a 5D grid with the specified maximum tile size along the
2061
 * last grid dimension.
2062
 *
2063
 * The function implements a parallel version of the following snippet:
2064
 *
2065
 *   for (size_t i = 0; i < range_i; i++)
2066
 *     for (size_t j = 0; j < range_j; j++)
2067
 *       for (size_t k = 0; k < range_k; k++)
2068
 *         for (size_t l = 0; l < range_l; l++)
2069
 *           for (size_t m = 0; m < range_m; m += tile_m)
2070
 *             function(context, i, j, k, l, m, min(range_m - m, tile_m));
2071
 *
2072
 * When the function returns, all items have been processed and the thread pool
2073
 * is ready for a new task.
2074
 *
2075
 * @note If multiple threads call this function with the same thread pool, the
2076
 *    calls are serialized.
2077
 *
2078
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2079
 *    is NULL, all items are processed serially on the calling thread.
2080
 * @param function    the function to call for each tile.
2081
 * @param context     the first argument passed to the specified function.
2082
 * @param range_i     the number of items to process along the first dimension
2083
 *    of the 5D grid.
2084
 * @param range_j     the number of items to process along the second dimension
2085
 *    of the 5D grid.
2086
 * @param range_k     the number of items to process along the third dimension
2087
 *    of the 5D grid.
2088
 * @param range_l     the number of items to process along the fourth dimension
2089
 *    of the 5D grid.
2090
 * @param range_m     the number of items to process along the fifth dimension
2091
 *    of the 5D grid.
2092
 * @param tile_m      the maximum number of items along the fifth dimension of
2093
 *    the 5D grid to process in one function call.
2094
 * @param flags       a bitwise combination of zero or more optional flags
2095
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2096
 */
2097
void pthreadpool_parallelize_5d_tile_1d(pthreadpool_t threadpool,
2098
                                        pthreadpool_task_5d_tile_1d_t function,
2099
                                        void* context, size_t range_i,
2100
                                        size_t range_j, size_t range_k,
2101
                                        size_t range_l, size_t range_m,
2102
                                        size_t tile_m, uint32_t flags);
2103
2104
/**
2105
 * Process items on a 5D grid with the specified maximum tile size along the
2106
 * last two grid dimensions.
2107
 *
2108
 * The function implements a parallel version of the following snippet:
2109
 *
2110
 *   for (size_t i = 0; i < range_i; i++)
2111
 *     for (size_t j = 0; j < range_j; j++)
2112
 *       for (size_t k = 0; k < range_k; k++)
2113
 *         for (size_t l = 0; l < range_l; l += tile_l)
2114
 *           for (size_t m = 0; m < range_m; m += tile_m)
2115
 *             function(context, i, j, k, l, m,
2116
 *               min(range_l - l, tile_l), min(range_m - m, tile_m));
2117
 *
2118
 * When the function returns, all items have been processed and the thread pool
2119
 * is ready for a new task.
2120
 *
2121
 * @note If multiple threads call this function with the same thread pool, the
2122
 *    calls are serialized.
2123
 *
2124
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2125
 *    is NULL, all items are processed serially on the calling thread.
2126
 * @param function    the function to call for each tile.
2127
 * @param context     the first argument passed to the specified function.
2128
 * @param range_i     the number of items to process along the first dimension
2129
 *    of the 5D grid.
2130
 * @param range_j     the number of items to process along the second dimension
2131
 *    of the 5D grid.
2132
 * @param range_k     the number of items to process along the third dimension
2133
 *    of the 5D grid.
2134
 * @param range_l     the number of items to process along the fourth dimension
2135
 *    of the 5D grid.
2136
 * @param range_m     the number of items to process along the fifth dimension
2137
 *    of the 5D grid.
2138
 * @param tile_l      the maximum number of items along the fourth dimension of
2139
 *    the 5D grid to process in one function call.
2140
 * @param tile_m      the maximum number of items along the fifth dimension of
2141
 *    the 5D grid to process in one function call.
2142
 * @param flags       a bitwise combination of zero or more optional flags
2143
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2144
 */
2145
void pthreadpool_parallelize_5d_tile_2d(pthreadpool_t threadpool,
2146
                                        pthreadpool_task_5d_tile_2d_t function,
2147
                                        void* context, size_t range_i,
2148
                                        size_t range_j, size_t range_k,
2149
                                        size_t range_l, size_t range_m,
2150
                                        size_t tile_l, size_t tile_m,
2151
                                        uint32_t flags);
2152
2153
/**
2154
 * Process items on a 6D grid.
2155
 *
2156
 * The function implements a parallel version of the following snippet:
2157
 *
2158
 *   for (size_t i = 0; i < range_i; i++)
2159
 *     for (size_t j = 0; j < range_j; j++)
2160
 *       for (size_t k = 0; k < range_k; k++)
2161
 *         for (size_t l = 0; l < range_l; l++)
2162
 *           for (size_t m = 0; m < range_m; m++)
2163
 *             for (size_t n = 0; n < range_n; n++)
2164
 *               function(context, i, j, k, l, m, n);
2165
 *
2166
 * When the function returns, all items have been processed and the thread pool
2167
 * is ready for a new task.
2168
 *
2169
 * @note If multiple threads call this function with the same thread pool, the
2170
 *    calls are serialized.
2171
 *
2172
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2173
 *    is NULL, all items are processed serially on the calling thread.
2174
 * @param function    the function to call for each tile.
2175
 * @param context     the first argument passed to the specified function.
2176
 * @param range_i     the number of items to process along the first dimension
2177
 *    of the 6D grid.
2178
 * @param range_j     the number of items to process along the second dimension
2179
 *    of the 6D grid.
2180
 * @param range_k     the number of items to process along the third dimension
2181
 *    of the 6D grid.
2182
 * @param range_l     the number of items to process along the fourth dimension
2183
 *    of the 6D grid.
2184
 * @param range_m     the number of items to process along the fifth dimension
2185
 *    of the 6D grid.
2186
 * @param range_n     the number of items to process along the sixth dimension
2187
 *    of the 6D grid.
2188
 * @param tile_n      the maximum number of items along the sixth dimension of
2189
 *    the 6D grid to process in one function call.
2190
 * @param flags       a bitwise combination of zero or more optional flags
2191
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2192
 */
2193
void pthreadpool_parallelize_6d(pthreadpool_t threadpool,
2194
                                pthreadpool_task_6d_t function, void* context,
2195
                                size_t range_i, size_t range_j, size_t range_k,
2196
                                size_t range_l, size_t range_m, size_t range_n,
2197
                                uint32_t flags);
2198
2199
/**
2200
 * Process items on a 6D grid with the specified maximum tile size along the
2201
 * last grid dimension.
2202
 *
2203
 * The function implements a parallel version of the following snippet:
2204
 *
2205
 *   for (size_t i = 0; i < range_i; i++)
2206
 *     for (size_t j = 0; j < range_j; j++)
2207
 *       for (size_t k = 0; k < range_k; k++)
2208
 *         for (size_t l = 0; l < range_l; l++)
2209
 *           for (size_t m = 0; m < range_m; m++)
2210
 *             for (size_t n = 0; n < range_n; n += tile_n)
2211
 *               function(context, i, j, k, l, m, n, min(range_n - n, tile_n));
2212
 *
2213
 * When the function returns, all items have been processed and the thread pool
2214
 * is ready for a new task.
2215
 *
2216
 * @note If multiple threads call this function with the same thread pool, the
2217
 *    calls are serialized.
2218
 *
2219
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2220
 *    is NULL, all items are processed serially on the calling thread.
2221
 * @param function    the function to call for each tile.
2222
 * @param context     the first argument passed to the specified function.
2223
 * @param range_i     the number of items to process along the first dimension
2224
 *    of the 6D grid.
2225
 * @param range_j     the number of items to process along the second dimension
2226
 *    of the 6D grid.
2227
 * @param range_k     the number of items to process along the third dimension
2228
 *    of the 6D grid.
2229
 * @param range_l     the number of items to process along the fourth dimension
2230
 *    of the 6D grid.
2231
 * @param range_m     the number of items to process along the fifth dimension
2232
 *    of the 6D grid.
2233
 * @param range_n     the number of items to process along the sixth dimension
2234
 *    of the 6D grid.
2235
 * @param tile_n      the maximum number of items along the sixth dimension of
2236
 *    the 6D grid to process in one function call.
2237
 * @param flags       a bitwise combination of zero or more optional flags
2238
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2239
 */
2240
void pthreadpool_parallelize_6d_tile_1d(pthreadpool_t threadpool,
2241
                                        pthreadpool_task_6d_tile_1d_t function,
2242
                                        void* context, size_t range_i,
2243
                                        size_t range_j, size_t range_k,
2244
                                        size_t range_l, size_t range_m,
2245
                                        size_t range_n, size_t tile_n,
2246
                                        uint32_t flags);
2247
2248
/**
2249
 * Process items on a 6D grid with the specified maximum tile size along the
2250
 * last two grid dimensions.
2251
 *
2252
 * The function implements a parallel version of the following snippet:
2253
 *
2254
 *   for (size_t i = 0; i < range_i; i++)
2255
 *     for (size_t j = 0; j < range_j; j++)
2256
 *       for (size_t k = 0; k < range_k; k++)
2257
 *         for (size_t l = 0; l < range_l; l++)
2258
 *           for (size_t m = 0; m < range_m; m += tile_m)
2259
 *             for (size_t n = 0; n < range_n; n += tile_n)
2260
 *               function(context, i, j, k, l, m, n,
2261
 *                 min(range_m - m, tile_m), min(range_n - n, tile_n));
2262
 *
2263
 * When the function returns, all items have been processed and the thread pool
2264
 * is ready for a new task.
2265
 *
2266
 * @note If multiple threads call this function with the same thread pool, the
2267
 *    calls are serialized.
2268
 *
2269
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2270
 *    is NULL, all items are processed serially on the calling thread.
2271
 * @param function    the function to call for each tile.
2272
 * @param context     the first argument passed to the specified function.
2273
 * @param range_i     the number of items to process along the first dimension
2274
 *    of the 6D grid.
2275
 * @param range_j     the number of items to process along the second dimension
2276
 *    of the 6D grid.
2277
 * @param range_k     the number of items to process along the third dimension
2278
 *    of the 6D grid.
2279
 * @param range_l     the number of items to process along the fourth dimension
2280
 *    of the 6D grid.
2281
 * @param range_m     the number of items to process along the fifth dimension
2282
 *    of the 6D grid.
2283
 * @param range_n     the number of items to process along the sixth dimension
2284
 *    of the 6D grid.
2285
 * @param tile_m      the maximum number of items along the fifth dimension of
2286
 *    the 6D grid to process in one function call.
2287
 * @param tile_n      the maximum number of items along the sixth dimension of
2288
 *    the 6D grid to process in one function call.
2289
 * @param flags       a bitwise combination of zero or more optional flags
2290
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2291
 */
2292
void pthreadpool_parallelize_6d_tile_2d(pthreadpool_t threadpool,
2293
                                        pthreadpool_task_6d_tile_2d_t function,
2294
                                        void* context, size_t range_i,
2295
                                        size_t range_j, size_t range_k,
2296
                                        size_t range_l, size_t range_m,
2297
                                        size_t range_n, size_t tile_m,
2298
                                        size_t tile_n, uint32_t flags);
2299
2300
/**
2301
 * Terminates threads in the thread pool and releases associated resources.
2302
 *
2303
 * @warning  Accessing the thread pool after a call to this function constitutes
2304
 *    undefined behaviour and may cause data corruption.
2305
 *
2306
 * @param[in,out]  threadpool  The thread pool to destroy.
2307
 */
2308
void pthreadpool_destroy(pthreadpool_t threadpool);
2309
2310
#ifndef PTHREADPOOL_NO_DEPRECATED_API
2311
2312
/* Legacy API for compatibility with pre-existing users (e.g. NNPACK) */
2313
#if defined(__GNUC__)
2314
#define PTHREADPOOL_DEPRECATED __attribute__((__deprecated__))
2315
#else
2316
#define PTHREADPOOL_DEPRECATED
2317
#endif
2318
2319
typedef void (*pthreadpool_function_1d_t)(void*, size_t);
2320
typedef void (*pthreadpool_function_1d_tiled_t)(void*, size_t, size_t);
2321
typedef void (*pthreadpool_function_2d_t)(void*, size_t, size_t);
2322
typedef void (*pthreadpool_function_2d_tiled_t)(void*, size_t, size_t, size_t,
2323
                                                size_t);
2324
typedef void (*pthreadpool_function_3d_tiled_t)(void*, size_t, size_t, size_t,
2325
                                                size_t, size_t, size_t);
2326
typedef void (*pthreadpool_function_4d_tiled_t)(void*, size_t, size_t, size_t,
2327
                                                size_t, size_t, size_t, size_t,
2328
                                                size_t);
2329
2330
void pthreadpool_compute_1d(pthreadpool_t threadpool,
2331
                            pthreadpool_function_1d_t function, void* argument,
2332
                            size_t range) PTHREADPOOL_DEPRECATED;
2333
2334
void pthreadpool_compute_1d_tiled(pthreadpool_t threadpool,
2335
                                  pthreadpool_function_1d_tiled_t function,
2336
                                  void* argument, size_t range,
2337
                                  size_t tile) PTHREADPOOL_DEPRECATED;
2338
2339
void pthreadpool_compute_2d(pthreadpool_t threadpool,
2340
                            pthreadpool_function_2d_t function, void* argument,
2341
                            size_t range_i,
2342
                            size_t range_j) PTHREADPOOL_DEPRECATED;
2343
2344
void pthreadpool_compute_2d_tiled(pthreadpool_t threadpool,
2345
                                  pthreadpool_function_2d_tiled_t function,
2346
                                  void* argument, size_t range_i,
2347
                                  size_t range_j, size_t tile_i,
2348
                                  size_t tile_j) PTHREADPOOL_DEPRECATED;
2349
2350
void pthreadpool_compute_3d_tiled(pthreadpool_t threadpool,
2351
                                  pthreadpool_function_3d_tiled_t function,
2352
                                  void* argument, size_t range_i,
2353
                                  size_t range_j, size_t range_k, size_t tile_i,
2354
                                  size_t tile_j,
2355
                                  size_t tile_k) PTHREADPOOL_DEPRECATED;
2356
2357
void pthreadpool_compute_4d_tiled(pthreadpool_t threadpool,
2358
                                  pthreadpool_function_4d_tiled_t function,
2359
                                  void* argument, size_t range_i,
2360
                                  size_t range_j, size_t range_k,
2361
                                  size_t range_l, size_t tile_i, size_t tile_j,
2362
                                  size_t tile_k,
2363
                                  size_t tile_l) PTHREADPOOL_DEPRECATED;
2364
2365
#endif /* PTHREADPOOL_NO_DEPRECATED_API */
2366
2367
#ifdef __cplusplus
2368
} /* extern "C" */
2369
#endif
2370
2371
#ifdef __cplusplus
2372
2373
namespace libpthreadpool {
2374
namespace detail {
2375
namespace {  // NOLINT: Naming this namespace would expose it.
2376
2377
template <class T>
2378
void call_wrapper_1d(void* arg, size_t i) {
2379
  (*static_cast<const T*>(arg))(i);
2380
}
2381
2382
template <class T>
2383
void call_wrapper_1d_tile_1d(void* arg, size_t range_i, size_t tile_i) {
2384
  (*static_cast<const T*>(arg))(range_i, tile_i);
2385
}
2386
2387
template <class T>
2388
void call_wrapper_1d_tile_1d_dynamic(void* arg, size_t range_i, size_t tile_i) {
2389
  (*static_cast<const T*>(arg))(range_i, tile_i);
2390
}
2391
2392
template <class T>
2393
void call_wrapper_2d(void* functor, size_t i, size_t j) {
2394
  (*static_cast<const T*>(functor))(i, j);
2395
}
2396
2397
template <class T>
2398
void call_wrapper_2d_tile_1d(void* functor, size_t i, size_t range_j,
2399
                             size_t tile_j) {
2400
  (*static_cast<const T*>(functor))(i, range_j, tile_j);
2401
}
2402
2403
template <class T>
2404
void call_wrapper_2d_tile_1d_dynamic(void* functor, size_t i, size_t range_j,
2405
                                     size_t tile_j) {
2406
  (*static_cast<const T*>(functor))(i, range_j, tile_j);
2407
}
2408
2409
template <class T>
2410
void call_wrapper_2d_tile_2d(void* functor, size_t range_i, size_t range_j,
2411
                             size_t tile_i, size_t tile_j) {
2412
  (*static_cast<const T*>(functor))(range_i, range_j, tile_i, tile_j);
2413
}
2414
2415
template <class T>
2416
void call_wrapper_2d_tile_2d_dynamic(void* functor, size_t range_i,
2417
                                     size_t range_j, size_t tile_i,
2418
                                     size_t tile_j) {
2419
  (*static_cast<const T*>(functor))(range_i, range_j, tile_i, tile_j);
2420
}
2421
2422
template <class T>
2423
void call_wrapper_3d(void* functor, size_t i, size_t j, size_t k) {
2424
  (*static_cast<const T*>(functor))(i, j, k);
2425
}
2426
2427
template <class T>
2428
void call_wrapper_3d_tile_1d(void* functor, size_t i, size_t j, size_t range_k,
2429
                             size_t tile_k) {
2430
  (*static_cast<const T*>(functor))(i, j, range_k, tile_k);
2431
}
2432
2433
template <class T>
2434
void call_wrapper_3d_tile_2d(void* functor, size_t i, size_t range_j,
2435
                             size_t range_k, size_t tile_j, size_t tile_k) {
2436
  (*static_cast<const T*>(functor))(i, range_j, range_k, tile_j, tile_k);
2437
}
2438
2439
template <class T>
2440
void call_wrapper_3d_tile_2d_dynamic(void* functor, size_t i, size_t range_j,
2441
                                     size_t range_k, size_t tile_j,
2442
                                     size_t tile_k) {
2443
  (*static_cast<const T*>(functor))(i, range_j, range_k, tile_j, tile_k);
2444
}
2445
2446
template <class T>
2447
void call_wrapper_4d(void* functor, size_t i, size_t j, size_t k, size_t l) {
2448
  (*static_cast<const T*>(functor))(i, j, k, l);
2449
}
2450
2451
template <class T>
2452
void call_wrapper_4d_tile_1d(void* functor, size_t i, size_t j, size_t k,
2453
                             size_t range_l, size_t tile_l) {
2454
  (*static_cast<const T*>(functor))(i, j, k, range_l, tile_l);
2455
}
2456
2457
template <class T>
2458
void call_wrapper_4d_tile_2d(void* functor, size_t i, size_t j, size_t range_k,
2459
                             size_t range_l, size_t tile_k, size_t tile_l) {
2460
  (*static_cast<const T*>(functor))(i, j, range_k, range_l, tile_k, tile_l);
2461
}
2462
2463
template <class T>
2464
void call_wrapper_4d_tile_2d_dynamic(void* functor, size_t i, size_t j,
2465
                                     size_t range_k, size_t range_l,
2466
                                     size_t tile_k, size_t tile_l) {
2467
  (*static_cast<const T*>(functor))(i, j, range_k, range_l, tile_k, tile_l);
2468
}
2469
2470
template <class T>
2471
void call_wrapper_5d(void* functor, size_t i, size_t j, size_t k, size_t l,
2472
                     size_t m) {
2473
  (*static_cast<const T*>(functor))(i, j, k, l, m);
2474
}
2475
2476
template <class T>
2477
void call_wrapper_5d_tile_1d(void* functor, size_t i, size_t j, size_t k,
2478
                             size_t l, size_t range_m, size_t tile_m) {
2479
  (*static_cast<const T*>(functor))(i, j, k, l, range_m, tile_m);
2480
}
2481
2482
template <class T>
2483
void call_wrapper_5d_tile_2d(void* functor, size_t i, size_t j, size_t k,
2484
                             size_t range_l, size_t range_m, size_t tile_l,
2485
                             size_t tile_m) {
2486
  (*static_cast<const T*>(functor))(i, j, k, range_l, range_m, tile_l, tile_m);
2487
}
2488
2489
template <class T>
2490
void call_wrapper_6d(void* functor, size_t i, size_t j, size_t k, size_t l,
2491
                     size_t m, size_t n) {
2492
  (*static_cast<const T*>(functor))(i, j, k, l, m, n);
2493
}
2494
2495
template <class T>
2496
void call_wrapper_6d_tile_1d(void* functor, size_t i, size_t j, size_t k,
2497
                             size_t l, size_t m, size_t range_n,
2498
                             size_t tile_n) {
2499
  (*static_cast<const T*>(functor))(i, j, k, l, m, range_n, tile_n);
2500
}
2501
2502
template <class T>
2503
void call_wrapper_6d_tile_2d(void* functor, size_t i, size_t j, size_t k,
2504
                             size_t l, size_t range_m, size_t range_n,
2505
                             size_t tile_m, size_t tile_n) {
2506
  (*static_cast<const T*>(functor))(i, j, k, l, range_m, range_n, tile_m,
2507
                                    tile_n);
2508
}
2509
2510
} /* namespace */
2511
} /* namespace detail */
2512
} /* namespace libpthreadpool */
2513
2514
/**
2515
 * Drop-in wrapper for the @a pthreadpool_scheduler that uses itself as its own
2516
 * context.
2517
 */
2518
class PthreadpoolExecutor : public pthreadpool_executor {
2519
 public:
2520
  using TaskFunction = void (*)(void*);
2521
2522
0
  PthreadpoolExecutor() {
2523
0
    num_threads = num_threads_impl;
2524
0
    schedule = schedule_impl;
2525
0
  }
2526
  virtual ~PthreadpoolExecutor() = default;
2527
2528
  /**
2529
   * Return the context of this @a PthreadpoolExecutor, e.g. for the @a
2530
   * pthreadpool_create_v2 function.
2531
   */
2532
0
  void* GetContext() { return this; }
2533
2534
  /**
2535
   * Override these methods for your own threadpool.
2536
   */
2537
  virtual int NumThreads() = 0;
2538
  virtual void Schedule(void* context, TaskFunction task) = 0;
2539
2540
 private:
2541
0
  static int num_threads_impl(void* executor) {
2542
0
    return reinterpret_cast<PthreadpoolExecutor*>(executor)->NumThreads();
2543
0
  }
2544
2545
0
  static void schedule_impl(void* executor, void* context, TaskFunction task) {
2546
0
    reinterpret_cast<PthreadpoolExecutor*>(executor)->Schedule(context, task);
2547
0
  }
2548
};
2549
2550
/**
2551
 * Process items on a 1D grid.
2552
 *
2553
 * The function implements a parallel version of the following snippet:
2554
 *
2555
 *   for (size_t i = 0; i < range; i++)
2556
 *     functor(i);
2557
 *
2558
 * When the function returns, all items have been processed and the thread pool
2559
 * is ready for a new task.
2560
 *
2561
 * @note If multiple threads call this function with the same thread pool, the
2562
 *    calls are serialized.
2563
 *
2564
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2565
 *    is NULL, all items are processed serially on the calling thread.
2566
 * @param functor     the functor to call for each item.
2567
 * @param range       the number of items on the 1D grid to process. The
2568
 *    specified functor will be called once for each item.
2569
 * @param flags       a bitwise combination of zero or more optional flags
2570
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2571
 */
2572
template <class T>
2573
inline void pthreadpool_parallelize_1d(pthreadpool_t threadpool,
2574
                                       const T& functor, size_t range,
2575
                                       uint32_t flags = 0) {
2576
  pthreadpool_parallelize_1d(
2577
      threadpool, &libpthreadpool::detail::call_wrapper_1d<const T>,
2578
      const_cast<void*>(static_cast<const void*>(&functor)), range, flags);
2579
}
2580
2581
/**
2582
 * Process items on a 1D grid with specified maximum tile size.
2583
 *
2584
 * The function implements a parallel version of the following snippet:
2585
 *
2586
 *   for (size_t i = 0; i < range; i += tile)
2587
 *     functor(i, min(range - i, tile));
2588
 *
2589
 * When the call returns, all items have been processed and the thread pool is
2590
 * ready for a new task.
2591
 *
2592
 * @note If multiple threads call this function with the same thread pool,
2593
 *    the calls are serialized.
2594
 *
2595
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2596
 *    is NULL, all items are processed serially on the calling thread.
2597
 * @param functor     the functor to call for each tile.
2598
 * @param range       the number of items on the 1D grid to process.
2599
 * @param tile        the maximum number of items on the 1D grid to process in
2600
 *    one functor call.
2601
 * @param flags       a bitwise combination of zero or more optional flags
2602
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2603
 */
2604
template <class T>
2605
inline void pthreadpool_parallelize_1d_tile_1d(pthreadpool_t threadpool,
2606
                                               const T& functor, size_t range,
2607
                                               size_t tile,
2608
                                               uint32_t flags = 0) {
2609
  pthreadpool_parallelize_1d_tile_1d(
2610
      threadpool, &libpthreadpool::detail::call_wrapper_1d_tile_1d<const T>,
2611
      const_cast<void*>(static_cast<const void*>(&functor)), range, tile,
2612
      flags);
2613
}
2614
2615
/**
2616
 * Process items on a 1D grid with specified prefered tile size.
2617
 *
2618
 * The function repeatedly calls
2619
 *
2620
 *   function(context, i, count)
2621
 *
2622
 * in parallel where `i` is in the range `[0, range)` and a multiple of the
2623
 * provided @a tile and `count` is an integer multiple of @a tile unless `i
2624
 * + count == range`.
2625
 *
2626
 * The `count`s are chosen such as to minimize the number of calls to @a
2627
 * function while keeping the computation load balanced across all threads.
2628
 *
2629
 * When the call returns, all items have been processed and the thread pool is
2630
 * ready for a new task.
2631
 *
2632
 * @note If multiple threads call this function with the same thread pool,
2633
 *    the calls are serialized.
2634
 *
2635
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2636
 *    is NULL, all items are processed serially on the calling thread.
2637
 * @param function    the function to call for each interval of the given range.
2638
 * @param context     the first argument passed to the specified function.
2639
 * @param range       the number of items on the 1D grid to process.
2640
 * @param tile        the preferred multiple number of items on the 1D grid to
2641
 *     process in each function call.
2642
 * @param flags       a bitwise combination of zero or more optional flags
2643
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2644
 */
2645
template <class T>
2646
inline void pthreadpool_parallelize_1d_tile_1d_dynamic(pthreadpool_t threadpool,
2647
                                                       const T& functor,
2648
                                                       size_t range,
2649
                                                       size_t tile,
2650
                                                       uint32_t flags = 0) {
2651
  pthreadpool_parallelize_1d_tile_1d_dynamic(
2652
      threadpool,
2653
      &libpthreadpool::detail::call_wrapper_1d_tile_1d_dynamic<const T>,
2654
      const_cast<void*>(static_cast<const void*>(&functor)), range, tile,
2655
      flags);
2656
}
2657
2658
/**
2659
 * Process items on a 2D grid.
2660
 *
2661
 * The function implements a parallel version of the following snippet:
2662
 *
2663
 *   for (size_t i = 0; i < range_i; i++)
2664
 *     for (size_t j = 0; j < range_j; j++)
2665
 *       functor(i, j);
2666
 *
2667
 * When the function returns, all items have been processed and the thread pool
2668
 * is ready for a new task.
2669
 *
2670
 * @note If multiple threads call this function with the same thread pool, the
2671
 *    calls are serialized.
2672
 *
2673
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2674
 *    is NULL, all items are processed serially on the calling thread.
2675
 * @param functor     the functor to call for each item.
2676
 * @param range_i     the number of items to process along the first dimension
2677
 *    of the 2D grid.
2678
 * @param range_j     the number of items to process along the second dimension
2679
 *    of the 2D grid.
2680
 * @param flags       a bitwise combination of zero or more optional flags
2681
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2682
 */
2683
template <class T>
2684
inline void pthreadpool_parallelize_2d(pthreadpool_t threadpool,
2685
                                       const T& functor, size_t range_i,
2686
                                       size_t range_j, uint32_t flags = 0) {
2687
  pthreadpool_parallelize_2d(
2688
      threadpool, &libpthreadpool::detail::call_wrapper_2d<const T>,
2689
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2690
      flags);
2691
}
2692
2693
/**
2694
 * Process items on a 2D grid with the specified maximum tile size along the
2695
 * last grid dimension.
2696
 *
2697
 * The function implements a parallel version of the following snippet:
2698
 *
2699
 *   for (size_t i = 0; i < range_i; i++)
2700
 *     for (size_t j = 0; j < range_j; j += tile_j)
2701
 *       functor(i, j, min(range_j - j, tile_j));
2702
 *
2703
 * When the function returns, all items have been processed and the thread pool
2704
 * is ready for a new task.
2705
 *
2706
 * @note If multiple threads call this function with the same thread pool, the
2707
 *    calls are serialized.
2708
 *
2709
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2710
 *    is NULL, all items are processed serially on the calling thread.
2711
 * @param functor     the functor to call for each tile.
2712
 * @param range_i     the number of items to process along the first dimension
2713
 *    of the 2D grid.
2714
 * @param range_j     the number of items to process along the second dimension
2715
 *    of the 2D grid.
2716
 * @param tile_j      the maximum number of items along the second dimension of
2717
 *    the 2D grid to process in one functor call.
2718
 * @param flags       a bitwise combination of zero or more optional flags
2719
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2720
 */
2721
template <class T>
2722
inline void pthreadpool_parallelize_2d_tile_1d(pthreadpool_t threadpool,
2723
                                               const T& functor, size_t range_i,
2724
                                               size_t range_j, size_t tile_j,
2725
                                               uint32_t flags = 0) {
2726
  pthreadpool_parallelize_2d_tile_1d(
2727
      threadpool, &libpthreadpool::detail::call_wrapper_2d_tile_1d<const T>,
2728
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2729
      tile_j, flags);
2730
}
2731
2732
/**
2733
 * Process items on a 2D grid with specified prefered tile size along the
2734
 * last grid dimension.
2735
 *
2736
 * The function repeatedly calls
2737
 *
2738
 *   function(context, i, j, count_j)
2739
 *
2740
 * in parallel where `i` is in the range `[0, range_i)`, `j` is in the range
2741
 * `[0, range_j)` and a multiple of the provided @a tile_j, and `count_j` is an
2742
 * integer multiple of @a tile_j unless `j + count_j == range_j`.
2743
 *
2744
 * The `count`s are chosen such as to minimize the number of calls to @a
2745
 * function while keeping the computation load balanced across all threads.
2746
 *
2747
 * When the call returns, all items have been processed and the thread pool is
2748
 * ready for a new task.
2749
 *
2750
 * @note If multiple threads call this function with the same thread pool,
2751
 *    the calls are serialized.
2752
 *
2753
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2754
 *    is NULL, all items are processed serially on the calling thread.
2755
 * @param function    the function to call for each interval of the given range.
2756
 * @param context     the first argument passed to the specified function.
2757
 * @param range_i       the number of items on the first dimension of the 2D
2758
 *     grid to process.
2759
 * @param range_j       the number of items on the second dimension of the 2D
2760
 *     grid to process.
2761
 * @param tile_j        the preferred multiple number of items on the second
2762
 *     dimension of the 2D grid to process in each function call.
2763
 * @param flags       a bitwise combination of zero or more optional flags
2764
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2765
 */
2766
template <class T>
2767
inline void pthreadpool_parallelize_2d_tile_1d_dynamic(
2768
    pthreadpool_t threadpool, const T& functor, size_t range_i, size_t range_j,
2769
    size_t tile_j, uint32_t flags = 0) {
2770
  pthreadpool_parallelize_2d_tile_1d_dynamic(
2771
      threadpool,
2772
      &libpthreadpool::detail::call_wrapper_2d_tile_1d_dynamic<const T>,
2773
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2774
      tile_j, flags);
2775
}
2776
2777
/**
2778
 * Process items on a 2D grid with the specified maximum tile size along each
2779
 * grid dimension.
2780
 *
2781
 * The function implements a parallel version of the following snippet:
2782
 *
2783
 *   for (size_t i = 0; i < range_i; i += tile_i)
2784
 *     for (size_t j = 0; j < range_j; j += tile_j)
2785
 *       functor(i, j,
2786
 *         min(range_i - i, tile_i), min(range_j - j, tile_j));
2787
 *
2788
 * When the function returns, all items have been processed and the thread pool
2789
 * is ready for a new task.
2790
 *
2791
 * @note If multiple threads call this function with the same thread pool, the
2792
 *    calls are serialized.
2793
 *
2794
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2795
 *    is NULL, all items are processed serially on the calling thread.
2796
 * @param functor     the functor to call for each tile.
2797
 * @param range_i     the number of items to process along the first dimension
2798
 *    of the 2D grid.
2799
 * @param range_j     the number of items to process along the second dimension
2800
 *    of the 2D grid.
2801
 * @param tile_j      the maximum number of items along the first dimension of
2802
 *    the 2D grid to process in one functor call.
2803
 * @param tile_j      the maximum number of items along the second dimension of
2804
 *    the 2D grid to process in one functor call.
2805
 * @param flags       a bitwise combination of zero or more optional flags
2806
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2807
 */
2808
template <class T>
2809
inline void pthreadpool_parallelize_2d_tile_2d(pthreadpool_t threadpool,
2810
                                               const T& functor, size_t range_i,
2811
                                               size_t range_j, size_t tile_i,
2812
                                               size_t tile_j,
2813
                                               uint32_t flags = 0) {
2814
  pthreadpool_parallelize_2d_tile_2d(
2815
      threadpool, &libpthreadpool::detail::call_wrapper_2d_tile_2d<const T>,
2816
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2817
      tile_i, tile_j, flags);
2818
}
2819
2820
/**
2821
 * Process items on a 2D grid with specified prefered tile size along each grid
2822
 * dimension.
2823
 *
2824
 * The function repeatedly calls
2825
 *
2826
 *   function(context, i, j, count_i, count_j)
2827
 *
2828
 * in parallel where `i` is in the range `[0, range_i)` and a multiple of the
2829
 * provided @a tile_i, `j` is in the range `[0, range_j)` and a multiple of the
2830
 * provided @a tile_j, and `count_i` and `count_j` are integer multiples of @a
2831
 * tile__i and @a tile_j, unless `i + count_i == range_i` or `j + count_j ==
2832
 * range_j`, respectivly.
2833
 *
2834
 * The `count`s are chosen such as to minimize the number of calls to @a
2835
 * function while keeping the computation load balanced across all threads.
2836
 *
2837
 * When the call returns, all items have been processed and the thread pool is
2838
 * ready for a new task.
2839
 *
2840
 * @note If multiple threads call this function with the same thread pool,
2841
 *    the calls are serialized.
2842
 *
2843
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2844
 *    is NULL, all items are processed serially on the calling thread.
2845
 * @param function    the function to call for each interval of the given range.
2846
 * @param context     the first argument passed to the specified function.
2847
 * @param range_i       the number of items on the first dimension of the 2D
2848
 *     grid to process.
2849
 * @param range_j       the number of items on the second dimension of the 2D
2850
 *     grid to process.
2851
 * @param tile_i        the preferred multiple number of items on the first
2852
 *     dimension of the 2D grid to process in each function call.
2853
 * @param tile_j        the preferred multiple number of items on the second
2854
 *     dimension of the 2D grid to process in each function call.
2855
 * @param flags       a bitwise combination of zero or more optional flags
2856
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2857
 */
2858
template <class T>
2859
inline void pthreadpool_parallelize_2d_tile_2d_dynamic(
2860
    pthreadpool_t threadpool, const T& functor, size_t range_i, size_t range_j,
2861
    size_t tile_i, size_t tile_j, uint32_t flags = 0) {
2862
  pthreadpool_parallelize_2d_tile_2d_dynamic(
2863
      threadpool,
2864
      &libpthreadpool::detail::call_wrapper_2d_tile_2d_dynamic<const T>,
2865
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2866
      tile_i, tile_j, flags);
2867
}
2868
2869
/**
2870
 * Process items on a 3D grid.
2871
 *
2872
 * The function implements a parallel version of the following snippet:
2873
 *
2874
 *   for (size_t i = 0; i < range_i; i++)
2875
 *     for (size_t j = 0; j < range_j; j++)
2876
 *       for (size_t k = 0; k < range_k; k++)
2877
 *         functor(i, j, k);
2878
 *
2879
 * When the function returns, all items have been processed and the thread pool
2880
 * is ready for a new task.
2881
 *
2882
 * @note If multiple threads call this function with the same thread pool, the
2883
 *    calls are serialized.
2884
 *
2885
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2886
 *    is NULL, all items are processed serially on the calling thread.
2887
 * @param functor     the functor to call for each tile.
2888
 * @param range_i     the number of items to process along the first dimension
2889
 *    of the 3D grid.
2890
 * @param range_j     the number of items to process along the second dimension
2891
 *    of the 3D grid.
2892
 * @param range_k     the number of items to process along the third dimension
2893
 *    of the 3D grid.
2894
 * @param flags       a bitwise combination of zero or more optional flags
2895
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2896
 */
2897
template <class T>
2898
inline void pthreadpool_parallelize_3d(pthreadpool_t threadpool,
2899
                                       const T& functor, size_t range_i,
2900
                                       size_t range_j, size_t range_k,
2901
                                       uint32_t flags = 0) {
2902
  pthreadpool_parallelize_3d(
2903
      threadpool, &libpthreadpool::detail::call_wrapper_3d<const T>,
2904
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2905
      range_k, flags);
2906
}
2907
2908
/**
2909
 * Process items on a 3D grid with the specified maximum tile size along the
2910
 * last grid dimension.
2911
 *
2912
 * The function implements a parallel version of the following snippet:
2913
 *
2914
 *   for (size_t i = 0; i < range_i; i++)
2915
 *     for (size_t j = 0; j < range_j; j++)
2916
 *       for (size_t k = 0; k < range_k; k += tile_k)
2917
 *         functor(i, j, k, min(range_k - k, tile_k));
2918
 *
2919
 * When the function returns, all items have been processed and the thread pool
2920
 * is ready for a new task.
2921
 *
2922
 * @note If multiple threads call this function with the same thread pool, the
2923
 *    calls are serialized.
2924
 *
2925
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2926
 *    is NULL, all items are processed serially on the calling thread.
2927
 * @param functor     the functor to call for each tile.
2928
 * @param range_i     the number of items to process along the first dimension
2929
 *    of the 3D grid.
2930
 * @param range_j     the number of items to process along the second dimension
2931
 *    of the 3D grid.
2932
 * @param range_k     the number of items to process along the third dimension
2933
 *    of the 3D grid.
2934
 * @param tile_k      the maximum number of items along the third dimension of
2935
 *    the 3D grid to process in one functor call.
2936
 * @param flags       a bitwise combination of zero or more optional flags
2937
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2938
 */
2939
template <class T>
2940
inline void pthreadpool_parallelize_3d_tile_1d(pthreadpool_t threadpool,
2941
                                               const T& functor, size_t range_i,
2942
                                               size_t range_j, size_t range_k,
2943
                                               size_t tile_k,
2944
                                               uint32_t flags = 0) {
2945
  pthreadpool_parallelize_3d_tile_1d(
2946
      threadpool, &libpthreadpool::detail::call_wrapper_3d_tile_1d<const T>,
2947
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2948
      range_k, tile_k, flags);
2949
}
2950
2951
/**
2952
 * Process items on a 3D grid with the specified maximum tile size along the
2953
 * last two grid dimensions.
2954
 *
2955
 * The function implements a parallel version of the following snippet:
2956
 *
2957
 *   for (size_t i = 0; i < range_i; i++)
2958
 *     for (size_t j = 0; j < range_j; j += tile_j)
2959
 *       for (size_t k = 0; k < range_k; k += tile_k)
2960
 *         functor(i, j, k,
2961
 *           min(range_j - j, tile_j), min(range_k - k, tile_k));
2962
 *
2963
 * When the function returns, all items have been processed and the thread pool
2964
 * is ready for a new task.
2965
 *
2966
 * @note If multiple threads call this function with the same thread pool, the
2967
 *    calls are serialized.
2968
 *
2969
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
2970
 *    is NULL, all items are processed serially on the calling thread.
2971
 * @param functor     the functor to call for each tile.
2972
 * @param range_i     the number of items to process along the first dimension
2973
 *    of the 3D grid.
2974
 * @param range_j     the number of items to process along the second dimension
2975
 *    of the 3D grid.
2976
 * @param range_k     the number of items to process along the third dimension
2977
 *    of the 3D grid.
2978
 * @param tile_j      the maximum number of items along the second dimension of
2979
 *    the 3D grid to process in one functor call.
2980
 * @param tile_k      the maximum number of items along the third dimension of
2981
 *    the 3D grid to process in one functor call.
2982
 * @param flags       a bitwise combination of zero or more optional flags
2983
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
2984
 */
2985
template <class T>
2986
inline void pthreadpool_parallelize_3d_tile_2d(pthreadpool_t threadpool,
2987
                                               const T& functor, size_t range_i,
2988
                                               size_t range_j, size_t range_k,
2989
                                               size_t tile_j, size_t tile_k,
2990
                                               uint32_t flags = 0) {
2991
  pthreadpool_parallelize_3d_tile_2d(
2992
      threadpool, &libpthreadpool::detail::call_wrapper_3d_tile_2d<const T>,
2993
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
2994
      range_k, tile_j, tile_k, flags);
2995
}
2996
2997
/**
2998
 * Process items on a 3D grid with specified prefered tile size along the last
2999
 * two grid dimensions.
3000
 *
3001
 * The function repeatedly calls
3002
 *
3003
 *   function(context, i, j, k, count_j, count_k)
3004
 *
3005
 * in parallel where:
3006
 *  - `i` is in the range `[0, range_i)`,
3007
 *  - `j` is in the range `[0, range_j)` and a multiple of the provided @a
3008
 *    tile_j,
3009
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
3010
 *    tile_k,
3011
 *  - `count_j` and `count_k` are integer multiples of @a tile__j and @a tile_k,
3012
 *    unless `j + count_j == range_j` or `k + count_k == range_k`, respectivly.
3013
 *
3014
 * The `count`s are chosen such as to minimize the number of calls to @a
3015
 * function while keeping the computation load balanced across all threads.
3016
 *
3017
 * When the call returns, all items have been processed and the thread pool is
3018
 * ready for a new task.
3019
 *
3020
 * @note If multiple threads call this function with the same thread pool,
3021
 *    the calls are serialized.
3022
 *
3023
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3024
 *    is NULL, all items are processed serially on the calling thread.
3025
 * @param function    the function to call for each interval of the given range.
3026
 * @param context     the first argument passed to the specified function.
3027
 * @param range_i       the number of items on the first dimension of the 3D
3028
 *     grid to process.
3029
 * @param range_j       the number of items on the second dimension of the 3D
3030
 *     grid to process.
3031
 * @param range_k       the number of items on the third dimension of the 3D
3032
 *     grid to process.
3033
 * @param tile_j        the preferred multiple number of items on the second
3034
 *     dimension of the 3D grid to process in each function call.
3035
 * @param tile_k        the preferred multiple number of items on the third
3036
 *     dimension of the 3D grid to process in each function call.
3037
 * @param flags       a bitwise combination of zero or more optional flags
3038
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3039
 */
3040
template <class T>
3041
inline void pthreadpool_parallelize_3d_tile_2d_dynamic(
3042
    pthreadpool_t threadpool, const T& functor, size_t range_i, size_t range_j,
3043
    size_t range_k, size_t tile_j, size_t tile_k, uint32_t flags = 0) {
3044
  pthreadpool_parallelize_3d_tile_2d_dynamic(
3045
      threadpool,
3046
      &libpthreadpool::detail::call_wrapper_3d_tile_2d_dynamic<const T>,
3047
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3048
      range_k, tile_j, tile_k, flags);
3049
}
3050
3051
/**
3052
 * Process items on a 4D grid.
3053
 *
3054
 * The function implements a parallel version of the following snippet:
3055
 *
3056
 *   for (size_t i = 0; i < range_i; i++)
3057
 *     for (size_t j = 0; j < range_j; j++)
3058
 *       for (size_t k = 0; k < range_k; k++)
3059
 *         for (size_t l = 0; l < range_l; l++)
3060
 *           functor(i, j, k, l);
3061
 *
3062
 * When the function returns, all items have been processed and the thread pool
3063
 * is ready for a new task.
3064
 *
3065
 * @note If multiple threads call this function with the same thread pool, the
3066
 *    calls are serialized.
3067
 *
3068
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3069
 *    is NULL, all items are processed serially on the calling thread.
3070
 * @param functor     the functor to call for each tile.
3071
 * @param range_i     the number of items to process along the first dimension
3072
 *    of the 4D grid.
3073
 * @param range_j     the number of items to process along the second dimension
3074
 *    of the 4D grid.
3075
 * @param range_k     the number of items to process along the third dimension
3076
 *    of the 4D grid.
3077
 * @param range_l     the number of items to process along the fourth dimension
3078
 *    of the 4D grid.
3079
 * @param flags       a bitwise combination of zero or more optional flags
3080
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3081
 */
3082
template <class T>
3083
inline void pthreadpool_parallelize_4d(pthreadpool_t threadpool,
3084
                                       const T& functor, size_t range_i,
3085
                                       size_t range_j, size_t range_k,
3086
                                       size_t range_l, uint32_t flags = 0) {
3087
  pthreadpool_parallelize_4d(
3088
      threadpool, &libpthreadpool::detail::call_wrapper_4d<const T>,
3089
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3090
      range_k, range_l, flags);
3091
}
3092
3093
/**
3094
 * Process items on a 4D grid with the specified maximum tile size along the
3095
 * last grid dimension.
3096
 *
3097
 * The function implements a parallel version of the following snippet:
3098
 *
3099
 *   for (size_t i = 0; i < range_i; i++)
3100
 *     for (size_t j = 0; j < range_j; j++)
3101
 *       for (size_t k = 0; k < range_k; k++)
3102
 *         for (size_t l = 0; l < range_l; l += tile_l)
3103
 *           functor(i, j, k, l, min(range_l - l, tile_l));
3104
 *
3105
 * When the function returns, all items have been processed and the thread pool
3106
 * is ready for a new task.
3107
 *
3108
 * @note If multiple threads call this function with the same thread pool, the
3109
 *    calls are serialized.
3110
 *
3111
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3112
 *    is NULL, all items are processed serially on the calling thread.
3113
 * @param functor     the functor to call for each tile.
3114
 * @param range_i     the number of items to process along the first dimension
3115
 *    of the 4D grid.
3116
 * @param range_j     the number of items to process along the second dimension
3117
 *    of the 4D grid.
3118
 * @param range_k     the number of items to process along the third dimension
3119
 *    of the 4D grid.
3120
 * @param range_l     the number of items to process along the fourth dimension
3121
 *    of the 4D grid.
3122
 * @param tile_l      the maximum number of items along the fourth dimension of
3123
 *    the 4D grid to process in one functor call.
3124
 * @param flags       a bitwise combination of zero or more optional flags
3125
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3126
 */
3127
template <class T>
3128
inline void pthreadpool_parallelize_4d_tile_1d(pthreadpool_t threadpool,
3129
                                               const T& functor, size_t range_i,
3130
                                               size_t range_j, size_t range_k,
3131
                                               size_t range_l, size_t tile_l,
3132
                                               uint32_t flags = 0) {
3133
  pthreadpool_parallelize_4d_tile_1d(
3134
      threadpool, &libpthreadpool::detail::call_wrapper_4d_tile_1d<const T>,
3135
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3136
      range_k, range_l, tile_l, flags);
3137
}
3138
3139
/**
3140
 * Process items on a 4D grid with the specified maximum tile size along the
3141
 * last two grid dimensions.
3142
 *
3143
 * The function implements a parallel version of the following snippet:
3144
 *
3145
 *   for (size_t i = 0; i < range_i; i++)
3146
 *     for (size_t j = 0; j < range_j; j++)
3147
 *       for (size_t k = 0; k < range_k; k += tile_k)
3148
 *         for (size_t l = 0; l < range_l; l += tile_l)
3149
 *           functor(i, j, k, l,
3150
 *             min(range_k - k, tile_k), min(range_l - l, tile_l));
3151
 *
3152
 * When the function returns, all items have been processed and the thread pool
3153
 * is ready for a new task.
3154
 *
3155
 * @note If multiple threads call this function with the same thread pool, the
3156
 *    calls are serialized.
3157
 *
3158
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3159
 *    is NULL, all items are processed serially on the calling thread.
3160
 * @param functor     the functor to call for each tile.
3161
 * @param range_i     the number of items to process along the first dimension
3162
 *    of the 4D grid.
3163
 * @param range_j     the number of items to process along the second dimension
3164
 *    of the 4D grid.
3165
 * @param range_k     the number of items to process along the third dimension
3166
 *    of the 4D grid.
3167
 * @param range_l     the number of items to process along the fourth dimension
3168
 *    of the 4D grid.
3169
 * @param tile_k      the maximum number of items along the third dimension of
3170
 *    the 4D grid to process in one functor call.
3171
 * @param tile_l      the maximum number of items along the fourth dimension of
3172
 *    the 4D grid to process in one functor call.
3173
 * @param flags       a bitwise combination of zero or more optional flags
3174
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3175
 */
3176
template <class T>
3177
inline void pthreadpool_parallelize_4d_tile_2d(pthreadpool_t threadpool,
3178
                                               const T& functor, size_t range_i,
3179
                                               size_t range_j, size_t range_k,
3180
                                               size_t range_l, size_t tile_k,
3181
                                               size_t tile_l,
3182
                                               uint32_t flags = 0) {
3183
  pthreadpool_parallelize_4d_tile_2d(
3184
      threadpool, &libpthreadpool::detail::call_wrapper_4d_tile_2d<const T>,
3185
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3186
      range_k, range_l, tile_k, tile_l, flags);
3187
}
3188
3189
/**
3190
 * Process items on a 4D grid with specified prefered tile size along the last
3191
 * two grid dimensions.
3192
 *
3193
 * The function repeatedly calls
3194
 *
3195
 *   function(context, i, j, k, l, count_k, count_l)
3196
 *
3197
 * in parallel where:
3198
 *  - `i` is in the range `[0, range_i)`,
3199
 *  - `j` is in the range `[0, range_j)`,
3200
 *  - `k` is in the range `[0, range_k)` and a multiple of the provided @a
3201
 *    tile_k,
3202
 *  - `l` is in the range `[0, range_l)` and a multiple of the provided @a
3203
 *    tile_l,
3204
 *  - `count_k` and `count_l` are integer multiples of @a tile_k and @a tile_l,
3205
 *    unless `k + count_k == range_k` or `l + count_l == range_l`, respectivly.
3206
 *
3207
 * The `count`s are chosen such as to minimize the number of calls to @a
3208
 * function while keeping the computation load balanced across all threads.
3209
 *
3210
 * When the call returns, all items have been processed and the thread pool is
3211
 * ready for a new task.
3212
 *
3213
 * @note If multiple threads call this function with the same thread pool,
3214
 *    the calls are serialized.
3215
 *
3216
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3217
 *                    is NULL, all items are processed serially on the calling
3218
 *                    thread.
3219
 * @param function    the function to call for each interval of the given range.
3220
 * @param context     the first argument passed to the specified function.
3221
 * @param range_i     the number of items on the first dimension of the 4D
3222
 *                    grid to process.
3223
 * @param range_j     the number of items on the second dimension of the 4D
3224
 *                    grid to process.
3225
 * @param range_k     the number of items on the third dimension of the 4D
3226
 *                    grid to process.
3227
 * @param range_l     the number of items on the fourth dimension of the 4D
3228
 *                    grid to process.
3229
 * @param tile_k      the preferred multiple number of items on the third
3230
 *                    dimension of the 4D grid to process in each function call.
3231
 * @param tile_l      the preferred multiple number of items on the fourth
3232
 *                    dimension of the 4D grid to process in each function call.
3233
 * @param flags       a bitwise combination of zero or more optional flags
3234
 *                    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or
3235
 *                    PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3236
 */
3237
template <class T>
3238
inline void pthreadpool_parallelize_4d_tile_2d_dynamic(
3239
    pthreadpool_t threadpool, const T& functor, size_t range_i, size_t range_j,
3240
    size_t range_k, size_t range_l, size_t tile_k, size_t tile_l,
3241
    uint32_t flags = 0) {
3242
  pthreadpool_parallelize_3d_tile_2d_dynamic(
3243
      threadpool,
3244
      &libpthreadpool::detail::call_wrapper_4d_tile_2d_dynamic<const T>,
3245
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3246
      range_k, range_l, tile_k, tile_l, flags);
3247
}
3248
3249
/**
3250
 * Process items on a 5D grid.
3251
 *
3252
 * The function implements a parallel version of the following snippet:
3253
 *
3254
 *   for (size_t i = 0; i < range_i; i++)
3255
 *     for (size_t j = 0; j < range_j; j++)
3256
 *       for (size_t k = 0; k < range_k; k++)
3257
 *         for (size_t l = 0; l < range_l; l++)
3258
 *           for (size_t m = 0; m < range_m; m++)
3259
 *             functor(i, j, k, l, m);
3260
 *
3261
 * When the function returns, all items have been processed and the thread pool
3262
 * is ready for a new task.
3263
 *
3264
 * @note If multiple threads call this function with the same thread pool, the
3265
 *    calls are serialized.
3266
 *
3267
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3268
 *    is NULL, all items are processed serially on the calling thread.
3269
 * @param functor     the functor to call for each tile.
3270
 * @param range_i     the number of items to process along the first dimension
3271
 *    of the 5D grid.
3272
 * @param range_j     the number of items to process along the second dimension
3273
 *    of the 5D grid.
3274
 * @param range_k     the number of items to process along the third dimension
3275
 *    of the 5D grid.
3276
 * @param range_l     the number of items to process along the fourth dimension
3277
 *    of the 5D grid.
3278
 * @param range_m     the number of items to process along the fifth dimension
3279
 *    of the 5D grid.
3280
 * @param flags       a bitwise combination of zero or more optional flags
3281
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3282
 */
3283
template <class T>
3284
inline void pthreadpool_parallelize_5d(pthreadpool_t threadpool,
3285
                                       const T& functor, size_t range_i,
3286
                                       size_t range_j, size_t range_k,
3287
                                       size_t range_l, size_t range_m,
3288
                                       uint32_t flags = 0) {
3289
  pthreadpool_parallelize_5d(
3290
      threadpool, &libpthreadpool::detail::call_wrapper_5d<const T>,
3291
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3292
      range_k, range_l, range_m, flags);
3293
}
3294
3295
/**
3296
 * Process items on a 5D grid with the specified maximum tile size along the
3297
 * last grid dimension.
3298
 *
3299
 * The function implements a parallel version of the following snippet:
3300
 *
3301
 *   for (size_t i = 0; i < range_i; i++)
3302
 *     for (size_t j = 0; j < range_j; j++)
3303
 *       for (size_t k = 0; k < range_k; k++)
3304
 *         for (size_t l = 0; l < range_l; l++)
3305
 *           for (size_t m = 0; m < range_m; m += tile_m)
3306
 *             functor(i, j, k, l, m, min(range_m - m, tile_m));
3307
 *
3308
 * When the function returns, all items have been processed and the thread pool
3309
 * is ready for a new task.
3310
 *
3311
 * @note If multiple threads call this function with the same thread pool, the
3312
 *    calls are serialized.
3313
 *
3314
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3315
 *    is NULL, all items are processed serially on the calling thread.
3316
 * @param functor     the functor to call for each tile.
3317
 * @param range_i     the number of items to process along the first dimension
3318
 *    of the 5D grid.
3319
 * @param range_j     the number of items to process along the second dimension
3320
 *    of the 5D grid.
3321
 * @param range_k     the number of items to process along the third dimension
3322
 *    of the 5D grid.
3323
 * @param range_l     the number of items to process along the fourth dimension
3324
 *    of the 5D grid.
3325
 * @param range_m     the number of items to process along the fifth dimension
3326
 *    of the 5D grid.
3327
 * @param tile_m      the maximum number of items along the fifth dimension of
3328
 *    the 5D grid to process in one functor call.
3329
 * @param flags       a bitwise combination of zero or more optional flags
3330
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3331
 */
3332
template <class T>
3333
inline void pthreadpool_parallelize_5d_tile_1d(pthreadpool_t threadpool,
3334
                                               const T& functor, size_t range_i,
3335
                                               size_t range_j, size_t range_k,
3336
                                               size_t range_l, size_t range_m,
3337
                                               size_t tile_m,
3338
                                               uint32_t flags = 0) {
3339
  pthreadpool_parallelize_5d_tile_1d(
3340
      threadpool, &libpthreadpool::detail::call_wrapper_5d_tile_1d<const T>,
3341
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3342
      range_k, range_l, range_m, tile_m, flags);
3343
}
3344
3345
/**
3346
 * Process items on a 5D grid with the specified maximum tile size along the
3347
 * last two grid dimensions.
3348
 *
3349
 * The function implements a parallel version of the following snippet:
3350
 *
3351
 *   for (size_t i = 0; i < range_i; i++)
3352
 *     for (size_t j = 0; j < range_j; j++)
3353
 *       for (size_t k = 0; k < range_k; k++)
3354
 *         for (size_t l = 0; l < range_l; l += tile_l)
3355
 *           for (size_t m = 0; m < range_m; m += tile_m)
3356
 *             functor(i, j, k, l, m,
3357
 *               min(range_l - l, tile_l), min(range_m - m, tile_m));
3358
 *
3359
 * When the function returns, all items have been processed and the thread pool
3360
 * is ready for a new task.
3361
 *
3362
 * @note If multiple threads call this function with the same thread pool, the
3363
 *    calls are serialized.
3364
 *
3365
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3366
 *    is NULL, all items are processed serially on the calling thread.
3367
 * @param functor     the functor to call for each tile.
3368
 * @param range_i     the number of items to process along the first dimension
3369
 *    of the 5D grid.
3370
 * @param range_j     the number of items to process along the second dimension
3371
 *    of the 5D grid.
3372
 * @param range_k     the number of items to process along the third dimension
3373
 *    of the 5D grid.
3374
 * @param range_l     the number of items to process along the fourth dimension
3375
 *    of the 5D grid.
3376
 * @param range_m     the number of items to process along the fifth dimension
3377
 *    of the 5D grid.
3378
 * @param tile_l      the maximum number of items along the fourth dimension of
3379
 *    the 5D grid to process in one functor call.
3380
 * @param tile_m      the maximum number of items along the fifth dimension of
3381
 *    the 5D grid to process in one functor call.
3382
 * @param flags       a bitwise combination of zero or more optional flags
3383
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3384
 */
3385
template <class T>
3386
inline void pthreadpool_parallelize_5d_tile_2d(pthreadpool_t threadpool,
3387
                                               const T& functor, size_t range_i,
3388
                                               size_t range_j, size_t range_k,
3389
                                               size_t range_l, size_t range_m,
3390
                                               size_t tile_l, size_t tile_m,
3391
                                               uint32_t flags = 0) {
3392
  pthreadpool_parallelize_5d_tile_2d(
3393
      threadpool, &libpthreadpool::detail::call_wrapper_5d_tile_2d<const T>,
3394
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3395
      range_k, range_l, range_m, tile_l, tile_m, flags);
3396
}
3397
3398
/**
3399
 * Process items on a 6D grid.
3400
 *
3401
 * The function implements a parallel version of the following snippet:
3402
 *
3403
 *   for (size_t i = 0; i < range_i; i++)
3404
 *     for (size_t j = 0; j < range_j; j++)
3405
 *       for (size_t k = 0; k < range_k; k++)
3406
 *         for (size_t l = 0; l < range_l; l++)
3407
 *           for (size_t m = 0; m < range_m; m++)
3408
 *             for (size_t n = 0; n < range_n; n++)
3409
 *               functor(i, j, k, l, m, n);
3410
 *
3411
 * When the function returns, all items have been processed and the thread pool
3412
 * is ready for a new task.
3413
 *
3414
 * @note If multiple threads call this function with the same thread pool, the
3415
 *    calls are serialized.
3416
 *
3417
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3418
 *    is NULL, all items are processed serially on the calling thread.
3419
 * @param functor     the functor to call for each tile.
3420
 * @param range_i     the number of items to process along the first dimension
3421
 *    of the 6D grid.
3422
 * @param range_j     the number of items to process along the second dimension
3423
 *    of the 6D grid.
3424
 * @param range_k     the number of items to process along the third dimension
3425
 *    of the 6D grid.
3426
 * @param range_l     the number of items to process along the fourth dimension
3427
 *    of the 6D grid.
3428
 * @param range_m     the number of items to process along the fifth dimension
3429
 *    of the 6D grid.
3430
 * @param range_n     the number of items to process along the sixth dimension
3431
 *    of the 6D grid.
3432
 * @param tile_n      the maximum number of items along the sixth dimension of
3433
 *    the 6D grid to process in one functor call.
3434
 * @param flags       a bitwise combination of zero or more optional flags
3435
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3436
 */
3437
template <class T>
3438
inline void pthreadpool_parallelize_6d(pthreadpool_t threadpool,
3439
                                       const T& functor, size_t range_i,
3440
                                       size_t range_j, size_t range_k,
3441
                                       size_t range_l, size_t range_m,
3442
                                       size_t range_n, uint32_t flags = 0) {
3443
  pthreadpool_parallelize_6d(
3444
      threadpool, &libpthreadpool::detail::call_wrapper_6d<const T>,
3445
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3446
      range_k, range_l, range_m, range_n, flags);
3447
}
3448
3449
/**
3450
 * Process items on a 6D grid with the specified maximum tile size along the
3451
 * last grid dimension.
3452
 *
3453
 * The function implements a parallel version of the following snippet:
3454
 *
3455
 *   for (size_t i = 0; i < range_i; i++)
3456
 *     for (size_t j = 0; j < range_j; j++)
3457
 *       for (size_t k = 0; k < range_k; k++)
3458
 *         for (size_t l = 0; l < range_l; l++)
3459
 *           for (size_t m = 0; m < range_m; m++)
3460
 *             for (size_t n = 0; n < range_n; n += tile_n)
3461
 *               functor(i, j, k, l, m, n, min(range_n - n, tile_n));
3462
 *
3463
 * When the function returns, all items have been processed and the thread pool
3464
 * is ready for a new task.
3465
 *
3466
 * @note If multiple threads call this function with the same thread pool, the
3467
 *    calls are serialized.
3468
 *
3469
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3470
 *    is NULL, all items are processed serially on the calling thread.
3471
 * @param functor     the functor to call for each tile.
3472
 * @param range_i     the number of items to process along the first dimension
3473
 *    of the 6D grid.
3474
 * @param range_j     the number of items to process along the second dimension
3475
 *    of the 6D grid.
3476
 * @param range_k     the number of items to process along the third dimension
3477
 *    of the 6D grid.
3478
 * @param range_l     the number of items to process along the fourth dimension
3479
 *    of the 6D grid.
3480
 * @param range_m     the number of items to process along the fifth dimension
3481
 *    of the 6D grid.
3482
 * @param range_n     the number of items to process along the sixth dimension
3483
 *    of the 6D grid.
3484
 * @param tile_n      the maximum number of items along the sixth dimension of
3485
 *    the 6D grid to process in one functor call.
3486
 * @param flags       a bitwise combination of zero or more optional flags
3487
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3488
 */
3489
template <class T>
3490
inline void pthreadpool_parallelize_6d_tile_1d(pthreadpool_t threadpool,
3491
                                               const T& functor, size_t range_i,
3492
                                               size_t range_j, size_t range_k,
3493
                                               size_t range_l, size_t range_m,
3494
                                               size_t range_n, size_t tile_n,
3495
                                               uint32_t flags = 0) {
3496
  pthreadpool_parallelize_6d_tile_1d(
3497
      threadpool, &libpthreadpool::detail::call_wrapper_6d_tile_1d<const T>,
3498
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3499
      range_k, range_l, range_m, range_n, tile_n, flags);
3500
}
3501
3502
/**
3503
 * Process items on a 6D grid with the specified maximum tile size along the
3504
 * last two grid dimensions.
3505
 *
3506
 * The function implements a parallel version of the following snippet:
3507
 *
3508
 *   for (size_t i = 0; i < range_i; i++)
3509
 *     for (size_t j = 0; j < range_j; j++)
3510
 *       for (size_t k = 0; k < range_k; k++)
3511
 *         for (size_t l = 0; l < range_l; l++)
3512
 *           for (size_t m = 0; m < range_m; m += tile_m)
3513
 *             for (size_t n = 0; n < range_n; n += tile_n)
3514
 *               functor(i, j, k, l, m, n,
3515
 *                 min(range_m - m, tile_m), min(range_n - n, tile_n));
3516
 *
3517
 * When the function returns, all items have been processed and the thread pool
3518
 * is ready for a new task.
3519
 *
3520
 * @note If multiple threads call this function with the same thread pool, the
3521
 *    calls are serialized.
3522
 *
3523
 * @param threadpool  the thread pool to use for parallelisation. If threadpool
3524
 *    is NULL, all items are processed serially on the calling thread.
3525
 * @param functor     the functor to call for each tile.
3526
 * @param range_i     the number of items to process along the first dimension
3527
 *    of the 6D grid.
3528
 * @param range_j     the number of items to process along the second dimension
3529
 *    of the 6D grid.
3530
 * @param range_k     the number of items to process along the third dimension
3531
 *    of the 6D grid.
3532
 * @param range_l     the number of items to process along the fourth dimension
3533
 *    of the 6D grid.
3534
 * @param range_m     the number of items to process along the fifth dimension
3535
 *    of the 6D grid.
3536
 * @param range_n     the number of items to process along the sixth dimension
3537
 *    of the 6D grid.
3538
 * @param tile_m      the maximum number of items along the fifth dimension of
3539
 *    the 6D grid to process in one functor call.
3540
 * @param tile_n      the maximum number of items along the sixth dimension of
3541
 *    the 6D grid to process in one functor call.
3542
 * @param flags       a bitwise combination of zero or more optional flags
3543
 *    (PTHREADPOOL_FLAG_DISABLE_DENORMALS or PTHREADPOOL_FLAG_DONT_SPIN_WORKERS)
3544
 */
3545
template <class T>
3546
inline void pthreadpool_parallelize_6d_tile_2d(
3547
    pthreadpool_t threadpool, const T& functor, size_t range_i, size_t range_j,
3548
    size_t range_k, size_t range_l, size_t range_m, size_t range_n,
3549
    size_t tile_m, size_t tile_n, uint32_t flags = 0) {
3550
  pthreadpool_parallelize_6d_tile_2d(
3551
      threadpool, &libpthreadpool::detail::call_wrapper_6d_tile_2d<const T>,
3552
      const_cast<void*>(static_cast<const void*>(&functor)), range_i, range_j,
3553
      range_k, range_l, range_m, range_n, tile_m, tile_n, flags);
3554
}
3555
3556
#endif /* __cplusplus */
3557
3558
#endif /* __PTHREADPOOL_INCLUDE_PTHREADPOOL_H_ */