使用任务使用 OpenMP 拆分动态变化的链表
Splitting up a dynamically changing linked list with OpenMP using tasks
我有一个理论上的 OpenMP 问题要问大家。
假设我执行以下操作:
#pragma omp parallel
{
#pragma omp single
{
while (!empty(linkedList)) {
#pragma omp task
doWork();
}
}
}
如果 doWork() 将元素重新添加到列表中会发生什么?
我担心的是,正在执行任务的单个线程将在执行任务的线程完成之前终止。这可能意味着遗漏了通过 doWork 函数重新添加到列表中的任何元素。有人知道这是怎么回事吗?
谢谢!
只需将生成器循环嵌入到另一个循环中,并在其间使用 taskwait
以确保所有任务都已完成执行。您还必须确保在代码的并发部分正确锁定链表,例如通过使用关键部分(如下所示)或更细粒度的锁。
doWork(element e)
{
// ...
#pragma omp critical(listOps)
insertElement(linkedList, newElement);
// ...
}
#pragma omp parallel
{
#pragma omp single
{
do
{
#pragma omp critical(listOps)
while (!empty(linkedList)) {
element e = removeElement(linkedList);
#pragma omp task
doWork(e);
}
#pragma omp taskwait
} while (!empty(linkedList));
}
}
我有一个理论上的 OpenMP 问题要问大家。 假设我执行以下操作:
#pragma omp parallel
{
#pragma omp single
{
while (!empty(linkedList)) {
#pragma omp task
doWork();
}
}
}
如果 doWork() 将元素重新添加到列表中会发生什么? 我担心的是,正在执行任务的单个线程将在执行任务的线程完成之前终止。这可能意味着遗漏了通过 doWork 函数重新添加到列表中的任何元素。有人知道这是怎么回事吗?
谢谢!
只需将生成器循环嵌入到另一个循环中,并在其间使用 taskwait
以确保所有任务都已完成执行。您还必须确保在代码的并发部分正确锁定链表,例如通过使用关键部分(如下所示)或更细粒度的锁。
doWork(element e)
{
// ...
#pragma omp critical(listOps)
insertElement(linkedList, newElement);
// ...
}
#pragma omp parallel
{
#pragma omp single
{
do
{
#pragma omp critical(listOps)
while (!empty(linkedList)) {
element e = removeElement(linkedList);
#pragma omp task
doWork(e);
}
#pragma omp taskwait
} while (!empty(linkedList));
}
}