[英]OpenMP parallelization
我正在编写一个具有科学目的的 C++ 程序。 该程序运行良好并且返回了良好的结果,因此我决定使用 OpenMP 提高其性能。 我要优化的循环如下:
//== #pragma omp parallel for private(i,j)
for (k=0; k < number; k++)
{
for (i=0; i < L; i++)
{
for (j=0; j < L; j++)
{
red[i][j] = UNDEFINED;
}
}
Point inicial = {L/2, L/2, OCCUPIED};
red[L/2][L/2] = OCCUPIED;
addToList(inicial, red, list, L,f);
oc.push_back(inicial);
while (list.size() > 0 && L > 0)
{
punto = selectPoint(red, list, generator, prob, p);
if (punto.state == OCCUPIED)
{
addToList(punto, red, list, L,f);
oc.push_back(punto);
}
else
{
out.push_back(punto);
}
}
L = auxL;
oc.clear();
out.clear();
list.clear();
}
f = f*1.0/(number*1.0);
if (f > 0.5)
{
inta = inta;
intb = p;
p = (inta + intb) / 2.0;
}
else if (f < 0.5)
{
intb = intb;
inta = p;
p = (inta + intb) / 2.0;
}
cout << p << endl;
}
上面评论了我对 OpenMP 的尝试。 如您所见,我已将i
和j
声明为私有,因为它们是在并行部分之前声明的。 我也尝试将L
设为私有,但没有结果。 只有分段错误和坏指针无处不在。 我认为问题在于 while 循环嵌套在里面。 我的问题是:在这种情况下, omp parallel for
正确? 或者我应该尝试只优化那个 while 循环? std::vector
是否会干扰 OpenMP?
注意: list
、 oc
和out
是std::vector<Point>
,而Point
是一个具有三个 int 属性的简单结构。 addToList
是一个内部没有循环的函数。
您可能想阅读 OpenMP 教程。 当您查看 OpenMP 代码时,您需要想象并行发生的事情。 拿
oc.push_back(inicial);
两个线程可以尝试同时执行此操作吗? 是的。 std::vector
是否支持并行性? 不。
上面的代码充满了这些东西。
如果要在 OpenMP ode 中使用数据结构,则需要使用 locks 。 根据我的个人经验,当发生这种情况时,重构算法比实际使用它们要好得多。 虽然 OpenMP + 锁定是可能的,但通常表明该想法存在问题(= 可能的主观观点)。
当前的答案指出了代码中的并发性,但请注意,并非所有数据结构都必须使用锁来实现以实现线程安全。 还有无lock-free
数据结构。 对于这种特殊情况,我们可以使用 Harris 无锁链表: https : //timharris.uk/papers/2001-disc.pdf
虽然我知道在这一点上向 OP 指出并发问题有很大帮助,但我想确保我们不会通过说锁对于实现线程安全是绝对必要的来传达错误信息。
#pragma omp parallel 指令定义了一段可以由多个线程同时执行的代码。 在您的情况下,由于您没有指定任何进一步的指令,您的并行区域将被每个线程执行一次。 为了实现并行行为,您可以尝试将循环分解为更小的任务(taskloop 指令将完成这项工作)。 这些任务将保留在任务池中,直到线程开始执行它们。 这样,您的循环将被分割并由您的线程执行,而不是让每个线程执行整个循环。
https://www.openmp.org/spec-html/5.0/openmpsu47.html这里是 taskloop 指令的官方 openMP 文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.