dougbinks / enkiTS

A permissively licensed C and C++ Task Scheduler for creating parallel programs. Requires C++11 support.
zlib License
1.66k stars 138 forks source link

parallel_for label:question #73

Closed ib00 closed 1 year ago

ib00 commented 2 years ago

Is there a simple implementation of parallel_for on top of enkiTS?

dougbinks commented 2 years ago

The ExecuteRange virtual function of an ITaskSet provides a parallel_for style interface, as does the TaskSet version which takes a lambda function.

So for example if you have a simple for loop such as:

for( int i = 0; i < count; ++i )
{
     a[i] = b[i] * c[i];
}

you can replace this with a lambda TastSet with set size equal to count, and the following task implementation:

// following is untested code
enki::TaskScheduler g_TS;
g_TS.Initialize();

enki::TaskSet task( 1024, [&]( enki::TaskSetPartition range, uint32_t threadnum  )
{  
    for( uint64_t i = range_.start; i < range_.end; ++i )
    {
         a[i] = b[i] * c[i];
    }
} );

g_TS.AddTaskSetToPipe( &task );
g_TS.WaitforTask( &task );

You could create a function which takes a lambda and does the above (except for initializing enkiTS which should usually be done only once).

ib00 commented 2 years ago

Thanks! I presume that TaskSet idea would also work with C API.

dougbinks commented 2 years ago

For the C API you can't use lambda's, but instead you use a simple function, take a look at the ParallelSum_c and the following based on the above example:

// warning untested code

void ParallelTaskSetFunc( uint32_t start_, uint32_t end_, uint32_t threadnum_, void* pArgs_ )
{
    for( uint64_t i = range_.start; i < range_.end; ++i )
    {
         // a, b, c are globals here, but you could pass them via pArgs_
         a[i] = b[i] * c[i];
    }
}

enkiTaskScheduler* pETS = enkiNewTaskScheduler();
enkiInitTaskScheduler( pETS );

enkiTaskSet* pParallelTaskSet = enkiCreateTaskSet( pETS, ParallelTaskSetFunc );
struct enkiParamsTaskSet parSumTaskParams = enkiGetParamsTaskSet( pParallelTaskSet );
parSumTaskParams.setSize = count;
enkiSetParamsTaskSet( pParallelTaskSet, parSumTaskParams );

enkiAddTaskSet( pETS, pParallelTaskSet );
enkiWaitForTaskSet( pETS, pParallelTaskSet );

Let me know if you have any further questions.

ib00 commented 2 years ago

Thanks! With minor modification, I can confirm that both C++ and C versions you gave work nicely.

I appreciate you making this library available.