OpenMP parallelization
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代码中使用数据结构,则需要使用锁。从我个人的经验来看,当这种情况发生时,重构算法比实际使用它们要好得多。虽然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文档