![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() ![]() |
![]() [Introduction] [Overview] [Core reference] [3D reference] [GUI] IndexEThreads_WaitForFinish EThreadSet_Run1D EThreads_OptimalThreadCount EThreads_WaitForFinishWait for threads to terminateSyntax Argument Description Waits for all threads in PThreadSet to terminate. Return value The number of threads terminated. See also EThreadSet_Run1DRun a task in multiple threadsSyntax Arguments Description Convenience function for running a task in multiple threads. Note that you only need thread constructor/destructor if you want to access that data outside the threads after they've completed. Otherwise you can just use local variables inside the PThreadMain() function and pass: sizeof(EThread), NULL, NULL for PThreadSize, PThreadInit and PThreadFree. Example typedef struct { EThreadSet1DCore; // EThreadSet1DMyData members E3dPolyGroup* PolyGroup; } EThreadSet1DMyData; ... // Progressbar update function. PCompleted is 0.0 .. 1.0 static void _Progress(const float PCompleted, EPointer PCustomData, void (*PAbortCallback)(EPointer PCustomData), EPointer PAbortFuncCustomData) { E3dProgressIndicator_Set(PCompleted, PAbortCallback, PAbortFuncCustomData);XeApp_Sync(Xe_App); } ... // Main function for multi-threaded tangent generation static void* _ThreadMain(void* PThread) { EThread* LThread = (EThread*)PThread; EThreadSet1DMyData* LThreadSet = (EThreadSet1DMyData*)LThread->ThreadSet; const EIndex LN = LThreadSet->NWorkUnits; E3dPolyGroup* LPolyGroup = LThreadSet->PolyGroup; while(1) { E_THREAD_LOCK(LThreadSet->GetWorkload); EIndex LPolygonIndex = LThreadSet->NextWorkUnit;LThreadSet->NextWorkUnit += 1;if(LPolygonIndex >= LN) { E_THREAD_UNLOCK(LThreadSet->GetWorkload); break; } E_THREAD_UNLOCK(LThreadSet->GetWorkload); _ProcessPolygon(LPolyGroup, LPolygonIndex); // Do the work on this Polygon } return(NULL); } ... EThreadSet1DMyData LThreadSet;EThreadSet1D_Init((EThreadSet1D*)<hreadSet); LThreadSet.ProgressMessage = "Processing Polygons"; LThreadSet.ProgressFunc = _Progress; LThreadSet.PolyGroup = LSomePolyGroup; // No custom per-thread data in this example, so we use sizeof(EThread) here and pass NULLs for the thread constructor and destructor EThreadSet_Run1D((EThreadSet1D*)<hreadSet, LSomePolyGroup->Polygons.Count, sizeof(EThread), NULL, NULL, _ThreadMain); EThreadSet1D_FreeContents((EThreadSet1D*)<hreadSet);Return value None. EThreads_OptimalThreadCountCalculate "optimal" thread count for an average processSyntax Arguments None. Description Returns an emperically-based "optimal" thread count baesd on tha available hardware threads and the measured cost of launching threads etc. This may be lower than the max threads on large HW thread-count systems. If the cost of your process is orders of magnitude higher than launching threads, you'll probably just want to use the max number of threads returned by E_GetCPUInfo(). For example, a path-traced with a complex scene might need that, but a simple scanline-parallelized image processing algorithm would have a diminishing return over, say 16 threads due to overhead cost of launching threads, memory bus contention etc. Here's the formula used in this function (LNThreads is the max available threads on the hardware): return(LNThreads <= LBaseline ? LNThreads : LBaseline + (LNThreads - LBaseline) * 1 / 8) Return value "Optimal" thread count See also |