NTrace
GPU ray tracing framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
MulticoreLauncher.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2011, NVIDIA Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of NVIDIA Corporation nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
29 #include "base/Timer.hpp"
30 
31 using namespace FW;
32 
33 //------------------------------------------------------------------------
34 
35 Spinlock MulticoreLauncher::s_lock;
36 S32 MulticoreLauncher::s_numInstances = 0;
37 S32 MulticoreLauncher::s_desiredThreads = -1;
38 
39 Monitor* MulticoreLauncher::s_monitor = NULL;
40 Deque<MulticoreLauncher::Task> MulticoreLauncher::s_pending;
41 S32 MulticoreLauncher::s_numThreads = 0;
42 
43 //------------------------------------------------------------------------
44 
46 : m_numTasks (0)
47 {
48  s_lock.enter();
49 
50  // First time => query the number of cores.
51 
52  if (s_desiredThreads == -1)
53  s_desiredThreads = getNumCores();
54 
55  // First instance => static init.
56 
57  if (s_numInstances++ == 0)
58  s_monitor = new Monitor;
59 
60  s_lock.leave();
61 }
62 
63 //------------------------------------------------------------------------
64 
66 {
67  popAll();
68  s_lock.enter();
69 
70  // Last instance => static deinit.
71 
72  if (--s_numInstances == 0)
73  {
74  // Kill threads.
75 
76  int old = s_desiredThreads;
77  s_desiredThreads = 0;
78  s_monitor->enter();
79  applyNumThreads();
80  s_monitor->leave();
81  s_desiredThreads = old;
82 
83  // Deinit static members.
84 
85  delete s_monitor;
86  s_monitor = NULL;
87  s_pending.reset();
88  }
89 
90  s_lock.leave();
91 }
92 
93 //------------------------------------------------------------------------
94 
95 MulticoreLauncher& MulticoreLauncher::push(TaskFunc func, void* data, int firstIdx, int numTasks)
96 {
97  FW_ASSERT(func != NULL);
98  FW_ASSERT(numTasks >= 0);
99 
100  if (numTasks <= 0)
101  return *this;
102 
103  s_monitor->enter();
104 
105  for (int i = 0; i < numTasks; i++)
106  {
107  Task& task = s_pending.addLast();
108  task.launcher = this;
109  task.func = func;
110  task.data = data;
111  task.idx = firstIdx + i;
112  task.result = NULL;
113  }
114  m_numTasks += numTasks;
115 
116  applyNumThreads();
117  s_monitor->notifyAll();
118  s_monitor->leave();
119  return *this;
120 }
121 
122 //------------------------------------------------------------------------
123 
125 {
127  s_monitor->enter();
128 
129  // Wait for a task to finish.
130 
131  while (!getNumFinished())
132  s_monitor->wait();
133 
134  // Pop from the queue.
135 
136  m_numTasks--;
137  Task task = m_finished.removeFirst();
138  s_monitor->leave();
139  return task;
140 }
141 
142 //------------------------------------------------------------------------
143 
145 {
146  return m_numTasks;
147 }
148 
149 //------------------------------------------------------------------------
150 
152 {
153  return m_finished.getSize();
154 }
155 
156 //------------------------------------------------------------------------
157 
158 void MulticoreLauncher::popAll(const String& progressMessage)
159 {
160  Timer timer;
161  F32 progress = 0.0f;
162  while (getNumTasks())
163  {
164  if (timer.getElapsed() > 0.1f)
165  {
166  printf("\r%s %d%%", progressMessage.getPtr(), (int)progress);
167  timer.start();
168  }
169  pop();
170  progress += (100.0f - progress) / (F32)(getNumTasks() + 1);
171  }
172  printf("\r%s 100%%\n", progressMessage.getPtr());
173 }
174 
175 //------------------------------------------------------------------------
176 
178 {
179  SYSTEM_INFO si;
180  GetSystemInfo(&si);
181  return si.dwNumberOfProcessors;
182 }
183 
184 //------------------------------------------------------------------------
185 
187 {
188  FW_ASSERT(numThreads > 0);
189  s_lock.enter();
190 
191  s_desiredThreads = numThreads;
192  if (s_numThreads != 0)
193  {
194  s_monitor->enter();
195  applyNumThreads();
196  s_monitor->leave();
197  }
198 
199  s_lock.leave();
200 }
201 
202 //------------------------------------------------------------------------
203 
204 void MulticoreLauncher::applyNumThreads(void) // Must have the monitor.
205 {
206  // Start new threads.
207 
208  while (s_numThreads < s_desiredThreads)
209  {
210  (new Thread)->start(threadFunc, NULL);
211  s_numThreads++;
212  }
213 
214  // Kill excess threads.
215 
216  if (s_numThreads > s_desiredThreads)
217  {
218  s_monitor->notifyAll();
219  while (s_numThreads > s_desiredThreads)
220  s_monitor->wait();
221  }
222 }
223 
224 //------------------------------------------------------------------------
225 
226 void MulticoreLauncher::threadFunc(void* param)
227 {
228  FW_UNREF(param);
230  s_monitor->enter();
231 
232  while (s_numThreads <= s_desiredThreads)
233  {
234  // No pending tasks => wait.
235 
236  if (!s_pending.getSize())
237  {
238  s_monitor->wait();
239  continue;
240  }
241 
242  // Pick a task.
243 
244  Task task = s_pending.removeFirst();
245  MulticoreLauncher* launcher = task.launcher;
246 
247  // Execute.
248 
249  s_monitor->leave();
250  task.func(task);
251  failIfError();
252  s_monitor->enter();
253 
254  // Mark as finished.
255 
256  launcher->m_finished.addLast(task);
257  s_monitor->notifyAll();
258  }
259 
260  s_numThreads--;
261  delete Thread::getCurrent();
262  s_monitor->notifyAll();
263  s_monitor->leave();
264 }
265 
266 //------------------------------------------------------------------------
#define FW_UNREF(X)
Definition: Defs.hpp:78
#define NULL
Definition: Defs.hpp:39
const char * getPtr(void) const
Definition: String.hpp:51
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid * data
Definition: DLLImports.inl:319
MulticoreLauncher & push(TaskFunc func, void *data, int firstIdx=0, int numTasks=1)
void setPriority(int priority)
Definition: Thread.cpp:359
void start(void)
Definition: Timer.hpp:42
void leave(void)
Definition: Thread.cpp:150
float F32
Definition: Defs.hpp:89
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint * param
Definition: DLLImports.inl:341
#define FW_ASSERT(X)
Definition: Defs.hpp:67
signed int S32
Definition: Defs.hpp:88
static int getNumCores(void)
CUdevice int ordinal char int CUdevice dev CUdevprop CUdevice dev CUcontext ctx CUcontext ctx CUcontext pctx CUmodule const void image CUmodule const void fatCubin CUfunction CUmodule const char name void p CUfunction unsigned int bytes CUtexref pTexRef CUtexref CUarray unsigned int Flags CUtexref int CUaddress_mode am CUtexref unsigned int Flags CUaddress_mode CUtexref int dim CUarray_format int CUtexref hTexRef CUfunction unsigned int numbytes CUfunction int float value CUfunction int CUtexref hTexRef CUfunction int int grid_height CUevent unsigned int Flags CUevent hEvent CUevent hEvent CUstream unsigned int Flags CUstream hStream GLuint bufferobj unsigned int CUdevice dev CUdeviceptr unsigned int CUmodule const char name CUdeviceptr unsigned int bytesize CUdeviceptr dptr void unsigned int bytesize void CUdeviceptr unsigned int ByteCount CUarray unsigned int CUdeviceptr unsigned int ByteCount CUarray unsigned int const void unsigned int ByteCount CUarray unsigned int CUarray unsigned int unsigned int ByteCount void CUarray unsigned int unsigned int CUstream hStream const CUDA_MEMCPY2D pCopy CUdeviceptr const void unsigned int CUstream hStream const CUDA_MEMCPY2D CUstream hStream CUdeviceptr unsigned char unsigned int N CUdeviceptr unsigned int unsigned int N CUdeviceptr unsigned int unsigned short unsigned int unsigned int Height CUarray const CUDA_ARRAY_DESCRIPTOR pAllocateArray CUarray const CUDA_ARRAY3D_DESCRIPTOR pAllocateArray unsigned int CUtexref CUdeviceptr unsigned int bytes CUcontext unsigned int CUdevice device GLenum texture GLenum GLuint buffer GLenum GLuint renderbuffer GLenum GLsizeiptr const GLvoid GLenum usage GLuint shader GLenum type GLsizei const GLuint framebuffers GLsizei const GLuint renderbuffers GLuint v GLuint v GLenum GLenum GLenum GLuint GLint level GLsizei GLuint framebuffers GLuint const GLchar name GLenum GLintptr GLsizeiptr GLvoid data GLuint GLenum GLint param GLuint GLenum GLint param GLhandleARB programObj GLenum GLenum GLsizei GLsizei height GLenum GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid pixels GLint GLsizei const GLfloat value GLint GLfloat GLfloat v1 GLint GLfloat GLfloat GLfloat v2 GLint GLsizei const GLfloat value GLint GLsizei GLboolean const GLfloat value GLuint program GLuint GLfloat GLfloat GLfloat z GLuint GLint GLenum GLboolean GLsizei const GLvoid pointer GLuint GLuint const GLchar name GLenum GLsizei GLenum GLsizei GLsizei height GLenum GLuint renderbuffer GLenum GLenum GLint params GLuint GLsizei range GLuint GLsizei const GLubyte GLsizei GLenum const GLvoid coords GLuint GLsizei GLsizei GLsizei const GLubyte GLsizei GLenum const GLvoid coords GLuint GLenum GLsizei const GLvoid pathString GLuint GLenum const GLvoid GLbitfield GLuint GLsizei GLenum GLuint GLfloat emScale GLuint GLuint srcPath GLuint GLuint GLenum const GLfloat transformValues GLuint GLenum GLint value GLuint GLenum GLfloat value GLenum func
Definition: DLLImports.inl:400
void notifyAll(void)
Definition: Thread.cpp:216
void enter(void)
Definition: Thread.cpp:124
void printf(const char *fmt,...)
Definition: Defs.cpp:225
int getNumFinished(void) const
int getNumTasks(void) const
void failIfError(void)
Definition: Defs.cpp:361
static Thread * getCurrent(void)
Definition: Thread.cpp:291
static void setNumThreads(int numThreads)
void leave(void)
Definition: Thread.cpp:61
F32 getElapsed(void)
Definition: Timer.hpp:44
void enter(void)
Definition: Thread.cpp:54
void wait(void)
Definition: Thread.cpp:167