我正在尝试使用OpenMP在树中的所有叶子中对数字求和进行树操作.我遇到的问题是我工作的树是不平衡的(孩子的数量不同,然后分支的大小也有所不同).
我目前有在这些树上工作的递归函数.我想要实现的是:
1)在第一个可能的机会拆分线程,说它是一个有2个孩子的节点
2)继续从两个结果线程中分割至少2-3个级别,以便所有线程都在工作
它看起来像这样:
if (node->depth <= 3) {
#pragma omp parallel
{
#pragma omp schedule(dynamic)
for (int i = 0; i < node->children_no; i++) {
int local_sum;
local_sum = sum_numbers(node->children[i])
#pragma omp critical
{
global_sum += local_sum;
}
}
}
} else {
/*run the for loop without parallel region*/
}
这里的问题是,当我允许嵌套并行时,似乎OpenMP在新团队中创建了很多线程.我想要实现的是:
1)创建新团队的每个线程都不能占用比MAX_THREADS更多的线程
2)一个for子循环在一个子树中结束后,其他人仍然在更大的子树中循环工作接管现在空闲的线程以更快地完成他们的工作
这样我希望永远不会有超过必要的线程但是它们都在一直工作,只要在所有for循环组合中有比未创建的线程更多未完成的任务.
从文档中看,它看起来像并行,只用于在并行区域中创建的线程.是否有可能使其按照描述的方式工作,或者我是否需要更改实现以首先列出各个分支的任务,然后在该列表上运行并行循环?
最佳答案 只是为了记录,我将基于高性能马克的评论(我也同意的评论)写出这个问题的答案.这里使用OpenMP任务将增加并行性的灵活性,即使树是不平衡的,支持递归并为所有线程产生足够的工作(尽管你应该使用诸如
Vampir,
Paraver和/或
HPCToolkit之类的工具来探索它).
结果代码可能看起来像
if (node->depth <= 3) {
#pragma omp parallel shared (global_sum)
{
for (int i = 0; i < node->children_no; i++) {
int local_sum;
#pragma omp single
#pragma omp task
{
local_sum = sum_numbers(node->children[i])
#pragma omp critical
global_sum += local_sum;
}
}
}
} else {
/*run the for loop without parallel region*/
}