2012-01-04 71 views
2

我对于并行编程相对较新,希望通过openmp完成C++中的以下任务。通过不同线程之间的(C++)openmp共享信息

我有一些(可以说4)相对复杂的对象/计算要做。它们都是相似的,但是太复杂以致无法并行化每一个(所以它们运行串行)。所以我的想法是为它们中的每一个使用不同的线程/ CPU,这意味着我想将计算分摊到我的核心上。尽管在这种情况下这可能不是最有效的并行性用法,但它可能是最容易实现的(因为每个计算的高复杂度)。

虽然这由

#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     obj[i].calculate();  
    } 
} 

欲这个对象之间交换的信息,例如一个整数(或更复杂的对象)的工作“一个”应被每个计算过程中修改(虽然我可以不预测何时和多少次,但尤其多于一次)。如果它被修改,那么这些信息也需要并入其他计算中。尽管信息的具体交换(再次)是相对复杂的,但这也是通过“计算”方法(隐含地)完成的。一般来说,这应该看起来像上面,如果加上整数“一”,这是所有的计算方法写和读:

int a; 
#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     obj[i].calculate();  
    } 
} 

所以我的问题是,如何防止“数据种族”在“一”?这意味着我怎样才能生成一个对象,每次只能由一个线程访问,而不用在“计算”方法本身中详细讨论? openmp是否提供了这个功能,如果没有,这个库是用来做什么的?

此致敬意!

+0

锁定'一个'的整个时间任何计算将需要它是相当简单的,但这将有效地序列化您的计算,是吗?你所有的计算都能够通过另一个线程异步改变可能复杂的'a'(我怀疑不是!)吗?如果不是,是否可以在每个计算中确定哪些点是安全的,以便他们接受新的'a'?如果他们在某个中间点接受新的'a',这是否会使计算运行的结果无效? – 2012-01-04 10:30:23

+0

我不确定我是否了解您的评论。计算可能是“长”(最多几天),“a”具有额外的特性,关于“更新”的知识可能会节省相当长的时间,但功能并不需要。所以检查一个新的“a”会经常重复,但大部分时间都会消极(没有新的“a”)。所以一个“旧”“一个”不会造成伤害,但是一个错误(异步?)会。在我看来,问题在于从一个线程修改“a”,而从另一个线程读取。 – Martin 2012-01-04 10:47:12

+0

我的问题在于理解如何改变参数(即使'干净'地完成'原子'来改变'a'),在计算的某个中间阶段和未知阶段可能会导致任何问题 - 一些计算将与旧的'a'和一些新的'a'一起完成 - 对我来说,这将是一件坏事。然而,你的回复标志着一些重要的信息 - 计算要求在适当的时候提供一个新的'a'(尽管如果现在没有'a'可用,请求可能会被拒绝)。这使事情变得更容易。 – 2012-01-04 11:03:23

回答

0

当然,您意识到方法calculate无法访问您发布的代码中的变量a。如果你想这样的工作,你可以写你的计算功能,内联和使用时要修改a关键部分:

int a; 
#pragma omp parallel 
{ 
    #pragma omp for 
    for(int i = 0; i < 4; i++) 
    { 
     // code of calculate 
     #pragma omp critical 
     { 
      // modify a 
     } 
     // other code 
    } 
} 
+0

在实际代码中,通过calculate方法中的(回调)指针访问“a”。计算函数非常长,并且在一定程度上不可预测运行时。此外,在每次计算过程中,“a”需要多次,所以我不能等待整个计算过程。所以我不确定内联是否足够。 – Martin 2012-01-04 10:51:39

+0

@Martin:我只是建议把修改的关键部分放在一个地方,而不是把它放在计算的末尾。 – Tudor 2012-01-04 10:57:35

+0

hm阅读这些评论,您很可能需要在计算方法中添加指令以确保正确更新。 – Bort 2012-01-04 11:02:10

1

从你的描述来看,我不知道并行执行是否会帮助你在任何时候每个线程必须等待更新信息a

无论如何,您可以使用flushatomiccritical指令更新没有竞争条件的变量。最好的选择很大程度上取决于哪些线程必须更新a或更新a

critical:所有线程执行的代码,但每一次一个

atomic:内存是针对多次写入保护,在内部被critical

flush代替:更新共享变量,并含蓄地critical称为

最后,barrier确保所有线程都已达到代码中的相同点。

我希望每个计算期间该对象之间进行交换的信息,用于 例如一个整数(或更复杂的对象)的“a”应该被修改 (虽然我无法预测的时间和频率, 但特别多于一次)。

这个说法有点刺激,因为你应该知道什么时候需要你的更新a。当您这样做时,您需要在所有线程中都有障碍,在临界区域更新a并继续并行执行。那么有多少线程更新a?主线程还是全部?

如果只有一个线程必须更新a,那么另一个选项是single指令。它的代码只能由一个隐含屏障的线程执行,并在执行后隐式刷新。这些是正确更新复杂对象a到所有线程的一般选项。祝你好运。

+0

+1,从我目前看到的,指针/ s的原子更新似乎应该完成这项工作。如果'a'是只读的计算器,一个静态指针可以适用于所有的线程,只要它们在它们的检查点创建本地副本并且'旧''a不会被销毁。 – 2012-01-04 11:31:51