我有一个可以轻松并行化的并行循环。我需要为循环实现自定义调度选项。为此,我将明确地将迭代分配给线程,而不是使用区域的标准并行,如:
#pragma omp parallel for
相反,我只是使用:
#pragama omp parallel [declarations]
到目前为止我的代码如下:
#define N 500
#pragma omp parallel
{
int num_threads = omp_get_num_threads();
int thread = omp_get_thread_num();
int start = N*thread/num_threads;
int end = N*(thread+1)/num_threads;
for (i=start; i<end; i++){
/* LOOP */
}
}
我需要应用一个调度算法,以便为每个线程分配一组本地迭代,我相信我已经完成了。每个本地集被拆分为每个线程执行的块。当线程完成它的块时,它会找到具有最多剩余块的线程并开始执行这些块。重复该过程直到没有剩余块。 我很难理解如何开始这个,因为我不完全确定如何找出最多的线程是什么,以及如何将本地迭代集分成块,同时仍然保持在平行区域。
答案 0 :(得分:1)
您需要实现的是work stealing算法。听起来你想要的是为每个线程分配一个双端队列(有时称为出队)。如果你允许任何线程从任何其他线程窃取工作,你将需要一个与每个队列相关联的锁,以防止两个线程试图窃取同一件工作。
您还希望将每个队列的大小作为键放入优先级队列,以便允许已完成的线程获取剩余工作量最多的线程。您还需要锁定该全局优先级队列,以便在执行更新时保持其完整性。
所有这一切,当可用时,#pragma omp for
的{{3}}时间表或产生dynamic
(来自#pragma omp task
)可能更可取。
如果您确实实现了自己的工作窃取算法,请记住根据一个指标来选择要窃取的线程,这个指标对于所有线程都是相同的,这通常会导致冲突(即,所有空闲线程都会尝试从同一个线程中窃取队列)。考虑根据地点选择在哪里偷工作。