我正在为优化任务运行一些C ++代码,我正在尝试使用OpenMP并行化它。我尝试在两个循环上使用#pragma omp parallel for
,但很快意识到它不起作用,所以我想设置一个条件来决定是否并行化外部或内部循环,具体取决于有多少外部迭代。 / p>
以下是代码:
std::vector<Sol> seeds; // vector with initial solutions
std::vector<Sol> sols (N_OUTER*N_INNER); // vector for output solutions
int N_OUTER; // typically 1-8
int N_INNER; // typically > 100
int PAR_THRESH; // this is the parameter I am interested in setting
#pragma omp parallel for if (N_OUTER >= PAR_THRESH)
for (int outer = 0; outer < N_OUTER; ++outer){
#pragma omp parallel for if (N_OUTER < PAR_THRESH)
for (int inner = 0; inner < N_INNER; ++inner){
sols[outer*N_INNER + inner] = solve(seeds[outer]);
}
}
这可以很好地决定哪个循环(内部或外部)并行化;但是,我正在尝试确定PAR_THRESH
的最佳值。
我的直觉说如果N_OUTER
为1,那么它不应该与外部循环并行,如果N_OUTER
大于可用的线程数,那么外部循环应该是要平行化的那个;因为它使用最大可用线程,并且线程尽可能长。我的问题是N_OUTER
是2还是3(4是可用的线程数)。
运行比较长的并行的2或3个线程是否更好;但是没有用完所有可用的线程?或者最好是串行运行2或3个外循环,同时利用内循环的最大线程数?
或者是否有一种权衡取舍,也许2次外循环迭代可能会浪费线程,但如果有3次外循环迭代,那么拥有更长的线程是有益的,尽管事实上一个线程仍未使用?
修改
已编辑的代码,用N_ITER
替换N_INNER
两个地方
答案 0 :(得分:1)
没有太多使用OpenMP的经验,但我找到了类似collapse
指令的内容:
https://software.intel.com/en-us/articles/openmp-loop-collapse-directive
Understanding the collapse clause in openmp
当内循环迭代次数不同时,似乎更合适。
-
另一方面:
在我看来,solve(...)
是无副作用的。似乎N_ITER也是N_INNER。
目前你计算解决N_INNER * N_OUTER次。
虽然减少不会降低O符号的复杂性,但假设它具有非常大的常数因子 - 它应该节省大量时间。您无法使用collapse
缓存结果,因此这可能会更好:
std::vector<Sol> sols_tmp (N_INNER);
#pragma omp parallel for
for (int i = 0; i < N_OUTER; ++i) {
sols_tmp[i] = solve(seeds[i]);
}
这只计算N_OUTER次。
因为solve为每一行返回相同的值:
#pragma omp parallel for
for (int i = 0; i < N_OUTER*N_INNER; ++i) {
sols[i] = sols_tmp[i/N_INNER];
}
当然,如果并行化适合于那些循环,则必须进行测量。