inline void TaskGroup::Launch(int baseIndex, int count) { for (int i = 0; i < count; ++i) { TaskInfo *ti = GetTaskInfo(baseIndex + i); int threadIndex = i; int threadCount = count; futures.push_back(hpx::async(ti->func, ti->data, threadIndex, threadCount, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2())); } }
inline void TaskGroup::Launch(int baseIndex, int count) { cilk_for(int i = 0; i < count; i++) { TaskInfo *ti = GetTaskInfo(baseIndex + i); // Actually run the task. // Cilk does not expose the task -> thread mapping so we pretend it's 1:1 ti->func(ti->data, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2()); } }
static void lRunTask(void *ti) { TaskInfo *taskInfo = (TaskInfo *)ti; // FIXME: these are bogus values; may cause bugs in code that depends // on them having unique values in different threads. int threadIndex = 0; int threadCount = 1; // Actually run the task taskInfo->func(taskInfo->data, threadIndex, threadCount, taskInfo->taskIndex, taskInfo->taskCount(), taskInfo->taskIndex0(), taskInfo->taskIndex1(), taskInfo->taskIndex2(), taskInfo->taskCount0(), taskInfo->taskCount1(), taskInfo->taskCount2()); }
inline void TaskGroup::Launch(int baseIndex, int count) { #pragma omp parallel for for(int i = 0; i < count; i++) { TaskInfo *ti = GetTaskInfo(baseIndex + i); // Actually run the task. int threadIndex = omp_get_thread_num(); int threadCount = omp_get_num_threads(); ti->func(ti->data, threadIndex, threadCount, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2()); } }
inline void TaskGroup::Launch(int baseIndex, int count) { for (int i = 0; i < count; i++) { tbbTaskGroup.run([=]() { TaskInfo *ti = GetTaskInfo(baseIndex + i); // TBB does not expose the task -> thread mapping so we pretend it's 1:1 int threadIndex = ti->taskIndex; int threadCount = ti->taskCount(); ti->func(ti->data, threadIndex, threadCount, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2()); }); } }
inline void TaskGroup::Launch(int baseIndex, int count) { tbb::parallel_for(0, count, [=](int i) { TaskInfo *ti = GetTaskInfo(baseIndex + i); // Actually run the task. // TBB does not expose the task -> thread mapping so we pretend it's 1:1 int threadIndex = ti->taskIndex; int threadCount = ti->taskCount(); ti->func(ti->data, threadIndex, threadCount, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2()); }); }
static void __cdecl lRunTask(LPVOID param) { TaskInfo *ti = (TaskInfo *)param; // Actually run the task. // FIXME: like the GCD implementation for OS X, this is passing bogus // values for the threadIndex and threadCount builtins, which in turn // will cause bugs in code that uses those. int threadIndex = 0; int threadCount = 1; ti->func(ti->data, threadIndex, threadCount, ti->taskIndex, ti->taskCount(), ti->taskIndex0(), ti->taskIndex1(), ti->taskIndex2(), ti->taskCount0(), ti->taskCount1(), ti->taskCount2()); // Signal the event that this task is done ti->taskEvent.set(); }
inline void TaskGroup::Sync() { DBG(fprintf(stderr, "syncing %p - %d unfinished\n", tg, numUnfinishedTasks)); while (numUnfinishedTasks > 0) { // All of the tasks in this group aren't finished yet. We'll try // to help out here since we don't have anything else to do... DBG(fprintf(stderr, "while syncing %p - %d unfinished\n", tg, numUnfinishedTasks)); // // Acquire the global task system mutex to grab a task to work on // int err; if ((err = pthread_mutex_lock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_lock: %s\n", strerror(err)); exit(1); } TaskInfo *myTask = NULL; TaskGroup *runtg = this; if (waitingTasks.size() > 0) { int taskNumber = waitingTasks.back(); waitingTasks.pop_back(); if (waitingTasks.size() == 0) { // There's nothing left to start running from this group, // so remove it from the active task list. activeTaskGroups.erase(std::find(activeTaskGroups.begin(), activeTaskGroups.end(), this)); inActiveList = false; } myTask = GetTaskInfo(taskNumber); DBG(fprintf(stderr, "running task %d from group %p in sync\n", taskNumber, tg)); } else { // Other threads are already working on all of the tasks in // this group, so we can't help out by running one ourself. // We'll try to run one from another group to make ourselves // useful here. if (activeTaskGroups.size() == 0) { // No active task groups left--there's nothing for us to do. if ((err = pthread_mutex_unlock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_unlock: %s\n", strerror(err)); exit(1); } // FIXME: We basically end up busy-waiting here, which is // extra wasteful in a world with hyper-threading. It would // be much better to put this thread to sleep on a // condition variable that was signaled when the last task // in this group was finished. #ifndef ISPC_IS_KNC usleep(1); #else _mm_delay_32(8); #endif continue; } // Get a task to run from another task group. runtg = activeTaskGroups.back(); assert(runtg->waitingTasks.size() > 0); int taskNumber = runtg->waitingTasks.back(); runtg->waitingTasks.pop_back(); if (runtg->waitingTasks.size() == 0) { // There's left to start running from this group, so remove // it from the active task list. activeTaskGroups.pop_back(); runtg->inActiveList = false; } myTask = runtg->GetTaskInfo(taskNumber); DBG(fprintf(stderr, "running task %d from other group %p in sync\n", taskNumber, runtg)); } if ((err = pthread_mutex_unlock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_unlock: %s\n", strerror(err)); exit(1); } // // Do work for _myTask_ // // FIXME: bogus values for thread index/thread count here as well.. myTask->func(myTask->data, 0, 1, myTask->taskIndex, myTask->taskCount(), myTask->taskIndex0(), myTask->taskIndex1(), myTask->taskIndex2(), myTask->taskCount0(), myTask->taskCount1(), myTask->taskCount2()); // // Decrement the number of unfinished tasks counter // lMemFence(); lAtomicAdd(&runtg->numUnfinishedTasks, -1); } DBG(fprintf(stderr, "sync for %p done!n", tg)); }
static void * lTaskEntry(void *arg) { int threadIndex = (int)((int64_t)arg); int threadCount = nThreads; while (1) { int err; // // Wait on the semaphore until we're woken up due to the arrival of // more work. // if ((err = sem_wait(workerSemaphore)) != 0) { fprintf(stderr, "Error from sem_wait: %s\n", strerror(err)); exit(1); } // // Acquire the mutex // if ((err = pthread_mutex_lock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_lock: %s\n", strerror(err)); exit(1); } if (activeTaskGroups.size() == 0) { // // Task queue is empty, go back and wait on the semaphore // if ((err = pthread_mutex_unlock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_unlock: %s\n", strerror(err)); exit(1); } continue; } // // Get the last task group on the active list and the last task // from its waiting tasks list. // TaskGroup *tg = activeTaskGroups.back(); assert(tg->waitingTasks.size() > 0); int taskNumber = tg->waitingTasks.back(); tg->waitingTasks.pop_back(); if (tg->waitingTasks.size() == 0) { // We just took the last task from this task group, so remove // it from the active list. activeTaskGroups.pop_back(); tg->inActiveList = false; } if ((err = pthread_mutex_unlock(&taskSysMutex)) != 0) { fprintf(stderr, "Error from pthread_mutex_unlock: %s\n", strerror(err)); exit(1); } // // And now actually run the task // DBG(fprintf(stderr, "running task %d from group %p\n", taskNumber, tg)); TaskInfo *myTask = tg->GetTaskInfo(taskNumber); myTask->func(myTask->data, threadIndex, threadCount, myTask->taskIndex, myTask->taskCount(), myTask->taskIndex0(), myTask->taskIndex1(), myTask->taskIndex2(), myTask->taskCount0(), myTask->taskCount1(), myTask->taskCount2()); // // Decrement the "number of unfinished tasks" counter in the task // group. // lMemFence(); lAtomicAdd(&tg->numUnfinishedTasks, -1); } pthread_exit(NULL); return 0; }