//get the first node from the front of the node list node_t *NextNodeFromList( void ) { node_t *node; ThreadLock(); numwaiting++; if ( !firstnode ) { if ( numwaiting >= GetNumThreads() ) { ThreadSemaphoreIncrease( GetNumThreads() ); } } //end if ThreadUnlock(); ThreadSemaphoreWait(); ThreadLock(); numwaiting--; node = firstnode; if ( firstnode ) { firstnode = firstnode->next; nodelistsize--; } //end if if ( !firstnode ) { lastnode = NULL; } ThreadUnlock(); return node; } //end of the function NextNodeFromList
void SetThreadCount(int num) { int curThreads = GetNumThreads(); if (curThreads < num) { #ifndef UNITSYNC if (hasOGLthreads) { try { for (int i = curThreads; i<num; ++i) { thread_group.push_back(new COffscreenGLThread(boost::bind(&WorkerLoop, i))); } } catch (const opengl_error& gle) { // shared gl context creation failed :< SetThreadCount(0); hasOGLthreads = false; curThreads = GetNumThreads(); } } #endif if (!hasOGLthreads) { for (int i = curThreads; i<num; ++i) { thread_group.push_back(new boost::thread(boost::bind(&WorkerLoop, i))); } } } else { for (int i = curThreads; i>num && i>1; --i) { assert(!thread_group.empty()); auto taskgroup = std::make_shared<ParallelTaskGroup<const std::function<void()>>>(); taskgroup->enqueue_unique(GetNumThreads() - 1, []{ exitThread = true; }); ThreadPool::PushTaskGroup(taskgroup); #ifndef UNITSYNC if (hasOGLthreads) { auto th = reinterpret_cast<COffscreenGLThread*>(thread_group.back()); th->join(); delete th; } else #endif { auto th = reinterpret_cast<boost::thread*>(thread_group.back()); th->join(); delete th; } thread_group.pop_back(); } if (num == 0) assert(thread_group.empty()); } }
void VulkanRenderer::OutputLog(std::ostream & fout) { fout << GetName() << "\n[" << GetNumVertices() << " vertices] [" << GetNumTriangles() << " triangles] [" << GetNumObjects() << " objects]" << std::endl; fout << "Threads: " << GetNumThreads() << std::endl; if(mUseInstancing) fout << "Pipeline: " << "Instancing" << std::endl; else if (mUseStaticCommandBuffer) fout << "Pipeline: " << "Static command buffers" << std::endl; else fout << "Pipeline: " << "Basic" << std::endl; }
/* * @brief Divides the HVL calculation between all available CPUs and waits for the calculation to finish * * @param[in,out] pv Double pointer to the HVLValues that are to be returned * @param[in] ctx Calculation context * @param[in] from Value of X to calculate from * @param[in] to Value of X to calculate to * @param[in] step Difference between two consecutive values of X * @param[in] a0 HVL a0 parameter * @param[in] a1 HVL a1 parameter * @param[in] a2 HVL a2 parameter * @param[in] a3 HVL a3 parameter * * @return True on success, false on failure */ bool LaunchWorkersAndWait(HVL_Range **pv, const HVL_Context *ctx, double from, double to, double step, double a0, double a1, double a2, double a3, fpcalcfun calcfun) { HVL_THREAD *threads; ThreadParams *tps = nullptr; bool bret; size_t idx; HVL_Pair *buffer; #ifdef LIBHVL_THREADING_WIN32 DWORD *threadIDs; #elif defined LIBHVL_THREADING_PTHREAD int ret; #else #error "No threading model has been specified" #endif // LIBHVL_THREADING_ const size_t count = (size_t)floor(((to - from) / step) + 0.5); if (count < 1) return false; const size_t numThreads = GetNumThreads(count); const size_t itersPerThread = count / numThreads; try { threads = new HVL_THREAD[numThreads]; } catch (std::bad_alloc&) { return false; } #ifdef LIBHVL_THREADING_WIN32 try { threadIDs = new DWORD[numThreads]; } catch (std::bad_alloc&) { delete[] threads; return false; } #endif // LIBHVL_THREADING_WIN32 try { tps = new ThreadParams[numThreads]; } catch (std::bad_alloc&) { bret = false; goto out; } *pv = HVL_alloc_range(count); if (*pv == nullptr) { bret = false; goto out; } buffer = (*pv)->p; for (idx = 0; idx < numThreads; idx++) { tps[idx].buffer = buffer + (itersPerThread * idx); tps[idx].ctx = ctx; tps[idx].from = from + (idx * step * itersPerThread); tps[idx].step = step; tps[idx].iters = itersPerThread; tps[idx].a0 = a0; tps[idx].a1 = a1; tps[idx].a2 = a2; tps[idx].a3 = a3; tps[idx].calcfun = calcfun; } /* Make an adjustment for the last thread */ tps[numThreads - 1].iters = count - (itersPerThread * (numThreads - 1)); /* Make sure that we do not leave out anything due to rounding */ /* Launch threads */ for (idx = 0; idx < numThreads; idx++) { #ifdef LIBHVL_THREADING_WIN32 threads[idx] = CreateThread(NULL, 0, WorkerFunc, &tps[idx], 0, &threadIDs[idx]); if (threads[idx] == 0) goto err_unwind; #elif defined LIBHVL_THREADING_PTHREAD ret = pthread_create(&threads[idx], NULL, WorkerFunc, &tps[idx]); if (ret) goto err_unwind; #endif // LIBHVL_THREADING_ } #ifdef LIBHVL_THREADING_WIN32 WaitForMultipleObjects(numThreads, threads, TRUE, INFINITE); for (idx = 0; idx < numThreads; idx++) CloseHandle(threads[idx]); #elif defined LIBHVL_THREADING_PTHREAD for (size_t idx = 0; idx < numThreads; idx++) pthread_join(threads[idx], NULL); #endif // LIBHVL_THREADING_ bret = true; goto out; /* Something went wrong when we were starting the workers, terminate all workers that might have been started and exit */ err_unwind: bret = false; for (;;) { #ifdef LIBHVL_THREADING_WIN32 TerminateThread(threads[idx], WAIT_OBJECT_0); CloseHandle(threads[idx]); #elif defined LIBHVL_THREADING_PTHREAD int _ret; void *retval; pthread_cancel(threads[idx]); _ret = pthread_join(threads[idx], &retval); if (_ret) abort(); /* Something has gone very wrong when killing the thread */ #endif // LIBHVL_THREADING_ if (idx == 0) break; else idx--; } HVL_free_range(*pv); *pv = nullptr; out: delete[] tps; delete[] threads; #ifdef LIBHVL_THREADING_WIN32 delete[] threadIDs; #endif // LIBHVL_THREADING_WIN32 return bret; }
void TaskManager :: Loop(int thd) { /* static Timer tADD("add entry counter"); static Timer tCASready1("spin-CAS ready tick1"); static Timer tCASready2("spin-CAS ready tick2"); static Timer tCASyield("spin-CAS yield"); static Timer tCAS1("spin-CAS wait"); static Timer texit("exit zone"); static Timer tdec("decrement"); */ thread_id = thd; int thds = GetNumThreads(); int mynode = num_nodes * thd/thds; NodeData & mynode_data = *(nodedata[mynode]); TaskInfo ti; ti.nthreads = thds; ti.thread_nr = thd; // ti.nnodes = num_nodes; // ti.node_nr = mynode; #ifdef USE_NUMA numa_run_on_node (mynode); #endif active_workers++; workers_on_node[mynode]++; int jobdone = 0; #ifdef USE_MKL auto mkl_max = mkl_get_max_threads(); mkl_set_num_threads_local(1); #endif while (!done) { if (complete[mynode] > jobdone) jobdone = complete[mynode]; if (jobnr == jobdone) { // RegionTracer t(ti.thread_nr, tCASyield, ti.task_nr); if(sleep) this_thread::sleep_for(chrono::microseconds(sleep_usecs)); else { #ifdef WIN32 this_thread::yield(); #else // WIN32 sched_yield(); #endif // WIN32 } continue; } { // RegionTracer t(ti.thread_nr, tADD, ti.task_nr); // non-atomic fast check ... if ( (mynode_data.participate & 1) == 0) continue; int oldval = mynode_data.participate += 2; if ( (oldval & 1) == 0) { // job not active, going out again mynode_data.participate -= 2; continue; } } if (startup_function) (*startup_function)(); IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes); try { while (1) { if (mynode_data.start_cnt >= mytasks.Size()) break; int mytask = mynode_data.start_cnt.fetch_add(1, memory_order_relaxed); if (mytask >= mytasks.Size()) break; ti.task_nr = mytasks.First()+mytask; ti.ntasks = ntasks; { RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr); (*func)(ti); } } } catch (Exception e) { { // cout << "got exception in TM" << endl; lock_guard<mutex> guard(copyex_mutex); delete ex; ex = new Exception (e); mynode_data.start_cnt = mytasks.Size(); } } #ifndef __MIC__ atomic_thread_fence (memory_order_release); #endif // __MIC__ if (cleanup_function) (*cleanup_function)(); jobdone = jobnr; mynode_data.participate-=2; { int oldpart = 1; if (mynode_data.participate.compare_exchange_strong (oldpart, 0)) { if (jobdone < jobnr.load()) { // reopen gate mynode_data.participate |= 1; } else { if (mynode != 0) mynode_data.start_cnt = 0; complete[mynode] = jobnr.load(); } } } } #ifdef USE_MKL mkl_set_num_threads_local(mkl_max); #endif workers_on_node[mynode]--; active_workers--; }
void TaskManager :: CreateJob (const function<void(TaskInfo&)> & afunc, int antasks) { if (num_threads == 1 || !task_manager || func) { if (startup_function) (*startup_function)(); TaskInfo ti; ti.ntasks = antasks; ti.thread_nr = 0; ti.nthreads = 1; // ti.node_nr = 0; ti.nnodes = 1; for (ti.task_nr = 0; ti.task_nr < antasks; ti.task_nr++) afunc(ti); if (cleanup_function) (*cleanup_function)(); return; } trace->StartJob(jobnr, afunc.target_type()); func = &afunc; ntasks.store (antasks); // , memory_order_relaxed); ex = nullptr; nodedata[0]->start_cnt.store (0, memory_order_relaxed); jobnr++; for (int j = 0; j < num_nodes; j++) nodedata[j]->participate |= 1; if (startup_function) (*startup_function)(); int thd = 0; int thds = GetNumThreads(); int mynode = num_nodes * thd/thds; IntRange mytasks = Range(int(ntasks)).Split (mynode, num_nodes); NodeData & mynode_data = *(nodedata[mynode]); TaskInfo ti; ti.nthreads = thds; ti.thread_nr = thd; // ti.nnodes = num_nodes; // ti.node_nr = mynode; try { while (1) { int mytask = mynode_data.start_cnt++; if (mytask >= mytasks.Size()) break; ti.task_nr = mytasks.First()+mytask; ti.ntasks = ntasks; { RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr); (*func)(ti); } } } catch (Exception e) { { lock_guard<mutex> guard(copyex_mutex); delete ex; ex = new Exception (e); mynode_data.start_cnt = mytasks.Size(); } } if (cleanup_function) (*cleanup_function)(); for (int j = 0; j < num_nodes; j++) if (workers_on_node[j]) { while (complete[j] != jobnr) _mm_pause(); } func = nullptr; if (ex) throw Exception (*ex); trace->StopJob(); }