Blender  V2.93
task_range.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include <cstdlib>
24 
25 #include "MEM_guardedalloc.h"
26 
27 #include "DNA_listBase.h"
28 
29 #include "BLI_task.h"
30 #include "BLI_threads.h"
31 
32 #include "atomic_ops.h"
33 
34 #ifdef WITH_TBB
35 # include <tbb/blocked_range.h>
36 # include <tbb/enumerable_thread_specific.h>
37 # include <tbb/parallel_for.h>
38 # include <tbb/parallel_reduce.h>
39 #endif
40 
41 #ifdef WITH_TBB
42 
43 /* Functor for running TBB parallel_for and parallel_reduce. */
44 struct RangeTask {
46  void *userdata;
47  const TaskParallelSettings *settings;
48 
49  void *userdata_chunk;
50 
51  /* Root constructor. */
52  RangeTask(TaskParallelRangeFunc func, void *userdata, const TaskParallelSettings *settings)
53  : func(func), userdata(userdata), settings(settings)
54  {
55  init_chunk(settings->userdata_chunk);
56  }
57 
58  /* Copy constructor. */
59  RangeTask(const RangeTask &other)
60  : func(other.func), userdata(other.userdata), settings(other.settings)
61  {
62  init_chunk(settings->userdata_chunk);
63  }
64 
65  /* Splitting constructor for parallel reduce. */
66  RangeTask(RangeTask &other, tbb::split /* unused */)
67  : func(other.func), userdata(other.userdata), settings(other.settings)
68  {
69  init_chunk(settings->userdata_chunk);
70  }
71 
72  ~RangeTask()
73  {
74  if (settings->func_free != nullptr) {
75  settings->func_free(userdata, userdata_chunk);
76  }
77  MEM_SAFE_FREE(userdata_chunk);
78  }
79 
80  void init_chunk(void *from_chunk)
81  {
82  if (from_chunk) {
83  userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "RangeTask");
84  memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size);
85  }
86  else {
87  userdata_chunk = nullptr;
88  }
89  }
90 
91  void operator()(const tbb::blocked_range<int> &r) const
92  {
93  tbb::this_task_arena::isolate([this, r] {
94  TaskParallelTLS tls;
95  tls.userdata_chunk = userdata_chunk;
96  for (int i = r.begin(); i != r.end(); ++i) {
97  func(userdata, i, &tls);
98  }
99  });
100  }
101 
102  void join(const RangeTask &other)
103  {
104  settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk);
105  }
106 };
107 
108 #endif
109 
110 void BLI_task_parallel_range(const int start,
111  const int stop,
112  void *userdata,
114  const TaskParallelSettings *settings)
115 {
116 #ifdef WITH_TBB
117  /* Multithreading. */
118  if (settings->use_threading && BLI_task_scheduler_num_threads() > 1) {
119  RangeTask task(func, userdata, settings);
120  const size_t grainsize = MAX2(settings->min_iter_per_thread, 1);
121  const tbb::blocked_range<int> range(start, stop, grainsize);
122 
123  if (settings->func_reduce) {
124  parallel_reduce(range, task);
125  if (settings->userdata_chunk) {
126  memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size);
127  }
128  }
129  else {
130  parallel_for(range, task);
131  }
132  return;
133  }
134 #endif
135 
136  /* Single threaded. Nothing to reduce as everything is accumulated into the
137  * main userdata chunk directly. */
138  TaskParallelTLS tls;
139  tls.userdata_chunk = settings->userdata_chunk;
140  for (int i = start; i < stop; i++) {
141  func(userdata, i, &tls);
142  }
143  if (settings->func_free != nullptr) {
144  settings->func_free(userdata, settings->userdata_chunk);
145  }
146 }
147 
149 {
150 #ifdef WITH_TBB
151  /* Get a unique thread ID for texture nodes. In the future we should get rid
152  * of the thread ID and change texture evaluation to not require per-thread
153  * storage that can't be efficiently allocated on the stack. */
154  static tbb::enumerable_thread_specific<int> tbb_thread_id(-1);
155  static int tbb_thread_id_counter = 0;
156 
157  int &thread_id = tbb_thread_id.local();
158  if (thread_id == -1) {
159  thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1);
160  if (thread_id >= BLENDER_MAX_THREADS) {
161  BLI_assert(!"Maximum number of threads exceeded for sculpting");
162  thread_id = thread_id % BLENDER_MAX_THREADS;
163  }
164  }
165  return thread_id;
166 #else
167  return 0;
168 #endif
169 }
#define BLI_assert(a)
Definition: BLI_assert.h:58
int BLI_task_scheduler_num_threads(void)
void(* TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls)
Definition: BLI_task.h:129
#define BLENDER_MAX_THREADS
Definition: BLI_threads.h:35
#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:47
struct blender::compositor::@172::@174 task
void split(const std::string &s, const char delim, std::vector< std::string > &tokens)
Definition: abc_util.cc:115
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
Definition: BLI_task.hh:62
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:158
TaskParallelFreeFunc func_free
Definition: BLI_task.h:160
size_t userdata_chunk_size
Definition: BLI_task.h:150
void * userdata_chunk
Definition: BLI_task.h:126
int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls))
Definition: task_range.cc:148
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110