Blender  V3.3
task_range.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
9 #include <cstdlib>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "DNA_listBase.h"
14 
15 #include "BLI_task.h"
16 #include "BLI_threads.h"
17 
18 #include "atomic_ops.h"
19 
20 #ifdef WITH_TBB
21 # include <tbb/blocked_range.h>
22 # include <tbb/enumerable_thread_specific.h>
23 # include <tbb/parallel_for.h>
24 # include <tbb/parallel_reduce.h>
25 #endif
26 
27 #ifdef WITH_TBB
28 
29 /* Functor for running TBB parallel_for and parallel_reduce. */
30 struct RangeTask {
32  void *userdata;
33  const TaskParallelSettings *settings;
34 
35  void *userdata_chunk;
36 
37  /* Root constructor. */
38  RangeTask(TaskParallelRangeFunc func, void *userdata, const TaskParallelSettings *settings)
39  : func(func), userdata(userdata), settings(settings)
40  {
41  init_chunk(settings->userdata_chunk);
42  }
43 
44  /* Copy constructor. */
45  RangeTask(const RangeTask &other)
46  : func(other.func), userdata(other.userdata), settings(other.settings)
47  {
48  init_chunk(settings->userdata_chunk);
49  }
50 
51  /* Splitting constructor for parallel reduce. */
52  RangeTask(RangeTask &other, tbb::split /* unused */)
53  : func(other.func), userdata(other.userdata), settings(other.settings)
54  {
55  init_chunk(settings->userdata_chunk);
56  }
57 
58  ~RangeTask()
59  {
60  if (settings->func_free != nullptr) {
61  settings->func_free(userdata, userdata_chunk);
62  }
63  MEM_SAFE_FREE(userdata_chunk);
64  }
65 
66  void init_chunk(void *from_chunk)
67  {
68  if (from_chunk) {
69  userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "RangeTask");
70  memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size);
71  }
72  else {
73  userdata_chunk = nullptr;
74  }
75  }
76 
77  void operator()(const tbb::blocked_range<int> &r) const
78  {
79  TaskParallelTLS tls;
80  tls.userdata_chunk = userdata_chunk;
81  for (int i = r.begin(); i != r.end(); ++i) {
82  func(userdata, i, &tls);
83  }
84  }
85 
86  void join(const RangeTask &other)
87  {
88  settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk);
89  }
90 };
91 
92 #endif
93 
94 void BLI_task_parallel_range(const int start,
95  const int stop,
96  void *userdata,
98  const TaskParallelSettings *settings)
99 {
100 #ifdef WITH_TBB
101  /* Multithreading. */
102  if (settings->use_threading && BLI_task_scheduler_num_threads() > 1) {
103  RangeTask task(func, userdata, settings);
104  const size_t grainsize = MAX2(settings->min_iter_per_thread, 1);
105  const tbb::blocked_range<int> range(start, stop, grainsize);
106 
107  if (settings->func_reduce) {
108  parallel_reduce(range, task);
109  if (settings->userdata_chunk) {
110  memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size);
111  }
112  }
113  else {
114  parallel_for(range, task);
115  }
116  return;
117  }
118 #endif
119 
120  /* Single threaded. Nothing to reduce as everything is accumulated into the
121  * main userdata chunk directly. */
122  TaskParallelTLS tls;
123  tls.userdata_chunk = settings->userdata_chunk;
124  for (int i = start; i < stop; i++) {
125  func(userdata, i, &tls);
126  }
127  if (settings->func_free != nullptr) {
128  settings->func_free(userdata, settings->userdata_chunk);
129  }
130 }
131 
133 {
134 #ifdef WITH_TBB
135  /* Get a unique thread ID for texture nodes. In the future we should get rid
136  * of the thread ID and change texture evaluation to not require per-thread
137  * storage that can't be efficiently allocated on the stack. */
138  static tbb::enumerable_thread_specific<int> tbb_thread_id(-1);
139  static int tbb_thread_id_counter = 0;
140 
141  int &thread_id = tbb_thread_id.local();
142  if (thread_id == -1) {
143  thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1);
145  BLI_assert_msg(0, "Maximum number of threads exceeded for sculpting");
147  }
148  }
149  return thread_id;
150 #else
151  return 0;
152 #endif
153 }
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
int BLI_task_scheduler_num_threads(void)
void(* TaskParallelRangeFunc)(void *__restrict userdata, int iter, const TaskParallelTLS *__restrict tls)
Definition: BLI_task.h:145
#define BLENDER_MAX_THREADS
Definition: BLI_threads.h:19
#define UNUSED(x)
#define MAX2(a, b)
These structs are the foundation for all linked lists in the library system.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE int32_t atomic_fetch_and_add_int32(int32_t *p, int32_t x)
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition: btTransform.h:90
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
struct blender::compositor::@179::@181 task
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:92
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:51
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition: BLI_task.hh:73
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:181
TaskParallelFreeFunc func_free
Definition: BLI_task.h:183
size_t userdata_chunk_size
Definition: BLI_task.h:169
void * userdata_chunk
Definition: BLI_task.h:142
int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls))
Definition: task_range.cc:132
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94