Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenlib/BLI_task.h
| Show All 37 Lines | |||||
| * | * | ||||
| * Central scheduler that holds running threads ready to execute tasks. A single | * Central scheduler that holds running threads ready to execute tasks. A single | ||||
| * queue holds the task from all pools. | * queue holds the task from all pools. | ||||
| * | * | ||||
| * Init/exit must be called before/after any task pools are created/freed, and | * Init/exit must be called before/after any task pools are created/freed, and | ||||
| * must be called from the main threads. All other scheduler and pool functions | * must be called from the main threads. All other scheduler and pool functions | ||||
| * are thread-safe. */ | * are thread-safe. */ | ||||
| typedef struct TaskScheduler TaskScheduler; | void BLI_task_scheduler_init(void); | ||||
| void BLI_task_scheduler_exit(void); | |||||
| TaskScheduler *BLI_task_scheduler_create(int num_threads); | int BLI_task_scheduler_num_threads(void); | ||||
jbakker: Remove line | |||||
| void BLI_task_scheduler_free(TaskScheduler *scheduler); | |||||
| int BLI_task_scheduler_num_threads(TaskScheduler *scheduler); | |||||
| /* Task Pool | /* Task Pool | ||||
| * | * | ||||
| * Pool of tasks that will be executed by the central TaskScheduler. For each | * Pool of tasks that will be executed by the central TaskScheduler. For each | ||||
| * pool, we can wait for all tasks to be done, or cancel them before they are | * pool, we can wait for all tasks to be done, or cancel them before they are | ||||
| * done. | * done. | ||||
| * | * | ||||
| * Running tasks may spawn new tasks. | * Running tasks may spawn new tasks. | ||||
| * | * | ||||
| * Pools may be nested, i.e. a thread running a task can create another task | * Pools may be nested, i.e. a thread running a task can create another task | ||||
| * pool with smaller tasks. When other threads are busy they will continue | * pool with smaller tasks. When other threads are busy they will continue | ||||
| * working on their own tasks, if not they will join in, no new threads will | * working on their own tasks, if not they will join in, no new threads will | ||||
| * be launched. | * be launched. | ||||
| */ | */ | ||||
| typedef enum TaskPriority { | typedef enum TaskPriority { | ||||
| TASK_PRIORITY_LOW, | TASK_PRIORITY_LOW, | ||||
| TASK_PRIORITY_HIGH, | TASK_PRIORITY_HIGH, | ||||
| } TaskPriority; | } TaskPriority; | ||||
| typedef struct TaskPool TaskPool; | typedef struct TaskPool TaskPool; | ||||
| typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid); | typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata); | ||||
| typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata); | typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata); | ||||
| TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority); | TaskPool *BLI_task_pool_create(void *userdata, TaskPriority priority); | ||||
| TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, | TaskPool *BLI_task_pool_create_background(void *userdata, TaskPriority priority); | ||||
| void *userdata, | TaskPool *BLI_task_pool_create_suspended(void *userdata, TaskPriority priority); | ||||
| TaskPriority priority); | TaskPool *BLI_task_pool_create_no_threads(void *userdata); | ||||
| TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, | TaskPool *BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority); | ||||
| void *userdata, | |||||
| TaskPriority priority); | |||||
| void BLI_task_pool_free(TaskPool *pool); | void BLI_task_pool_free(TaskPool *pool); | ||||
| void BLI_task_pool_push(TaskPool *pool, | void BLI_task_pool_push(TaskPool *pool, | ||||
| TaskRunFunction run, | TaskRunFunction run, | ||||
| void *taskdata, | void *taskdata, | ||||
| bool free_taskdata, | bool free_taskdata, | ||||
| TaskFreeFunction freedata); | TaskFreeFunction freedata); | ||||
| void BLI_task_pool_push_from_thread(TaskPool *pool, | |||||
| TaskRunFunction run, | |||||
| void *taskdata, | |||||
| bool free_taskdata, | |||||
| TaskFreeFunction freedata, | |||||
| int thread_id); | |||||
| /* work and wait until all tasks are done */ | /* work and wait until all tasks are done */ | ||||
| void BLI_task_pool_work_and_wait(TaskPool *pool); | void BLI_task_pool_work_and_wait(TaskPool *pool); | ||||
| /* work and wait until all tasks are done, then reset to the initial suspended state */ | |||||
| void BLI_task_pool_work_wait_and_reset(TaskPool *pool); | |||||
| /* cancel all tasks, keep worker threads running */ | /* cancel all tasks, keep worker threads running */ | ||||
| void BLI_task_pool_cancel(TaskPool *pool); | void BLI_task_pool_cancel(TaskPool *pool); | ||||
| /* for worker threads, test if canceled */ | /* for worker threads, test if canceled */ | ||||
| bool BLI_task_pool_canceled(TaskPool *pool); | bool BLI_task_pool_canceled(TaskPool *pool); | ||||
| /* optional userdata pointer to pass along to run function */ | /* optional userdata pointer to pass along to run function */ | ||||
| void *BLI_task_pool_user_data(TaskPool *pool); | void *BLI_task_pool_user_data(TaskPool *pool); | ||||
| /* optional mutex to use from run function */ | /* optional mutex to use from run function */ | ||||
| ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); | ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); | ||||
| /* Thread ID of thread that created the task pool. */ | |||||
| int BLI_task_pool_creator_thread_id(TaskPool *pool); | |||||
| /* Delayed push, use that to reduce thread overhead by accumulating | |||||
| * all new tasks into local queue first and pushing it to scheduler | |||||
| * from within a single mutex lock. | |||||
| */ | |||||
| void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id); | |||||
| void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id); | |||||
| /* Parallel for routines */ | /* Parallel for routines */ | ||||
| typedef enum eTaskSchedulingMode { | |||||
| /* Task scheduler will divide overall work into equal chunks, scheduling | |||||
| * even chunks to all worker threads. | |||||
| * Least run time benefit, ideal for cases when each task requires equal | |||||
| * amount of compute power. | |||||
| */ | |||||
| TASK_SCHEDULING_STATIC, | |||||
| /* Task scheduler will schedule small amount of work to each worker thread. | |||||
| * Has more run time overhead, but deals much better with cases when each | |||||
| * part of the work requires totally different amount of compute power. | |||||
| */ | |||||
| TASK_SCHEDULING_DYNAMIC, | |||||
| } eTaskSchedulingMode; | |||||
| /* Per-thread specific data passed to the callback. */ | /* Per-thread specific data passed to the callback. */ | ||||
| typedef struct TaskParallelTLS { | typedef struct TaskParallelTLS { | ||||
| /* Identifier of the thread who this data belongs to. */ | |||||
| int thread_id; | |||||
| /* Copy of user-specifier chunk, which is copied from original chunk to all | /* Copy of user-specifier chunk, which is copied from original chunk to all | ||||
| * worker threads. This is similar to OpenMP's firstprivate. | * worker threads. This is similar to OpenMP's firstprivate. | ||||
| */ | */ | ||||
| void *userdata_chunk; | void *userdata_chunk; | ||||
| } TaskParallelTLS; | } TaskParallelTLS; | ||||
| typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, | typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, | ||||
| const int iter, | const int iter, | ||||
| const TaskParallelTLS *__restrict tls); | const TaskParallelTLS *__restrict tls); | ||||
| typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, | typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, | ||||
| void *__restrict chunk_join, | void *__restrict chunk_join, | ||||
| void *__restrict chunk); | void *__restrict chunk); | ||||
| typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk); | typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk); | ||||
| typedef struct TaskParallelSettings { | typedef struct TaskParallelSettings { | ||||
| /* Whether caller allows to do threading of the particular range. | /* Whether caller allows to do threading of the particular range. | ||||
| * Usually set by some equation, which forces threading off when threading | * Usually set by some equation, which forces threading off when threading | ||||
| * overhead becomes higher than speed benefit. | * overhead becomes higher than speed benefit. | ||||
| * BLI_task_parallel_range() by itself will always use threading when range | * BLI_task_parallel_range() by itself will always use threading when range | ||||
| * is higher than a chunk size. As in, threading will always be performed. | * is higher than a chunk size. As in, threading will always be performed. | ||||
| */ | */ | ||||
| bool use_threading; | bool use_threading; | ||||
| /* Scheduling mode to use for this parallel range invocation. */ | |||||
| eTaskSchedulingMode scheduling_mode; | |||||
| /* Each instance of looping chunks will get a copy of this data | /* Each instance of looping chunks will get a copy of this data | ||||
| * (similar to OpenMP's firstprivate). | * (similar to OpenMP's firstprivate). | ||||
| */ | */ | ||||
| void *userdata_chunk; /* Pointer to actual data. */ | void *userdata_chunk; /* Pointer to actual data. */ | ||||
| size_t userdata_chunk_size; /* Size of that data. */ | size_t userdata_chunk_size; /* Size of that data. */ | ||||
| /* Function called from calling thread once whole range have been | /* Function called from calling thread once whole range have been | ||||
| * processed. | * processed. | ||||
| */ | */ | ||||
| Show All 18 Lines | |||||
| } TaskParallelSettings; | } TaskParallelSettings; | ||||
| BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings); | BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings); | ||||
| void BLI_task_parallel_range(const int start, | void BLI_task_parallel_range(const int start, | ||||
| const int stop, | const int stop, | ||||
| void *userdata, | void *userdata, | ||||
| TaskParallelRangeFunc func, | TaskParallelRangeFunc func, | ||||
| TaskParallelSettings *settings); | const TaskParallelSettings *settings); | ||||
| typedef struct TaskParallelRangePool TaskParallelRangePool; | |||||
| struct TaskParallelRangePool *BLI_task_parallel_range_pool_init( | |||||
| const struct TaskParallelSettings *settings); | |||||
| void BLI_task_parallel_range_pool_push(struct TaskParallelRangePool *range_pool, | |||||
| const int start, | |||||
| const int stop, | |||||
| void *userdata, | |||||
| TaskParallelRangeFunc func, | |||||
| const struct TaskParallelSettings *settings); | |||||
| void BLI_task_parallel_range_pool_work_and_wait(struct TaskParallelRangePool *range_pool); | |||||
| void BLI_task_parallel_range_pool_free(struct TaskParallelRangePool *range_pool); | |||||
| /* This data is shared between all tasks, its access needs thread lock or similar protection. | /* This data is shared between all tasks, its access needs thread lock or similar protection. | ||||
| */ | */ | ||||
| typedef struct TaskParallelIteratorStateShared { | typedef struct TaskParallelIteratorStateShared { | ||||
| /* Maximum amount of items to acquire at once. */ | /* Maximum amount of items to acquire at once. */ | ||||
| int chunk_size; | int chunk_size; | ||||
| /* Next item to be acquired. */ | /* Next item to be acquired. */ | ||||
| void *next_item; | void *next_item; | ||||
| Show All 38 Lines | void BLI_task_parallel_mempool(struct BLI_mempool *mempool, | ||||
| TaskParallelMempoolFunc func, | TaskParallelMempoolFunc func, | ||||
| const bool use_threading); | const bool use_threading); | ||||
| /* TODO(sergey): Think of a better place for this. */ | /* TODO(sergey): Think of a better place for this. */ | ||||
| BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings) | BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings) | ||||
| { | { | ||||
| memset(settings, 0, sizeof(*settings)); | memset(settings, 0, sizeof(*settings)); | ||||
| settings->use_threading = true; | settings->use_threading = true; | ||||
| settings->scheduling_mode = TASK_SCHEDULING_STATIC; | |||||
| /* Use default heuristic to define actual chunk size. */ | /* Use default heuristic to define actual chunk size. */ | ||||
| settings->min_iter_per_thread = 0; | settings->min_iter_per_thread = 0; | ||||
| } | } | ||||
| /* Don't use this, store any thread specific data in tls->userdata_chunk instead. | |||||
| * Ony here for code to be removed. */ | |||||
| int BLI_task_parallel_thread_id(const TaskParallelTLS *tls); | |||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| } | } | ||||
| #endif | #endif | ||||
| #endif | #endif | ||||
Remove line