2011-05-10 141 views
3

我对OpenMP稍微有点新,但是对于并行处理有一定的经验。我之前和boost::threads一起工作过,现在我正在用openmp进行测试。OpenMP共享数据

的问题是,我不知道如何处理共享数据访问,因为我真的不知道是什么的OpenMP并行循环内共享数据对象在内部做。

我现在正在做什么(这是迄今为止的工作):我用mmap从磁盘读取文件到内存中。在内存映射部分之后,我收到一个char指针。

OpenMP现在可以在OpenMP parallel for循环中使用该指针并在线程之间共享数据。我现在可以在映射和共享文件内搜索正则表达式匹配,多个线程检查每个字符串与(很长的)正则表达式列表。

我做了这个名单(含正则表达式向量)OpenMP的循环中私有的,所以每个线程都有它自己的这个名单的副本。

这里谈到的问题:

大幅度增加我的应用程序的性能,我需要能够一旦他们匹配字符串移除此向量(regex-)项目。

现在所有其他活动线程都需要尽快从列表中删除此项目。

所以我做了这个名单OpenMP的循环内共享数据对象,但现在我在运行时获取分段错误,当我尝试写(vector.erase(项目#))到列表中。

With boost :: threads我只是在写/读它时使用了一个互斥锁来锁定这个对象。

OpenMP的,但似乎处理大多数同步自身的所以现在我不知道什么是使用OpenMP这是一个新的我,当来处理这个问题的正确途径。

+0

你有一个最小的例子来证明这个问题吗? – 2011-05-10 06:49:45

回答

1

您可以通过创建关键部分来实现此目的。

#pragma omp critical 
{ 
    ...some synchronized code... 
} 

编辑: 删除关于“的#pragma OMP原子”,因为它不能执行原子所需要的操作的部分。

+0

'#pragma omp atomic'在允许的表达式中受到很大限制。您提供的示例不符合OpenMP规范。我建议你从答案中删除相应的部分。 – 2011-05-10 10:44:30

+0

你绝对正确,很久以前我用openMP :) – David 2011-05-10 10:57:54

3

为了同步,可以使用#pragma omp critical或者可能使用的OpenMP锁定例程(omp_{init,set,unset,destroy}_lock)。

#pragma omp critical的好处是简单,并忽略编译时并行区域是已知的由单个线程的执行能力。缺点是仅适用于单个并行区域,并且该区域内的全局效应:其他线程不能执行该区域中的任何其他关键部分。

OpenMP锁定例程与大多数其他可用锁相似,例如,那些pthreads或Boost(RAII除外)。你初始化一个锁定对象,然后用它来保护某些关键部分,并在不需要时摧毁它。这些锁可用于保护从不同并行区域访问数据,构建分布式锁定方案等。但总是会产生一定数量的开销,并且与#pragma omp critical相比,肯定会使用更多的“毛茸茸”。

但是,我会质疑并行解决方案的设计。从矢量中间擦除元素会使所有迭代器失效,并移动元素。擦除被认为是一种罕见的操作(否则,即使在我认为的连续代码中,向量的选择也是有问题的),但是由于上述影响,你必须保护向量的所有读取,并且这可能是昂贵的。读/写锁可能会有所缓解,但这些在OpenMP中不可用,因此您需要使用平台特定的接口或第三方库。

我认为有以下可能会更好地工作:

  • 你保持正则表达式向量私人,并补充说,表明有一定的正则表达式是否仍然有效与否的标志的相同大小的共享载体。
  • 在从私有向量应用某个正则表达式之前,代码检查共享向量中是否该正则表达式未被某个其他线程“擦除”。如果是,则跳过正则表达式。
  • 找到匹配后,代码将与当前正则表达式对应的共享向量的元素标记为“已擦除”,以便从现在开始将其忽略。

在此方案中,存在种族进行读/写的标志:标志可能被设置为“删除”第二天目前它被另一个线程读为“有效”。结果,两个不同的线程可能同时为相同的正则表达式找到匹配。然而,我相信这个问题存在于你当前的解决方案中,其中所有的正则表达式容器都是私有的,以及具有共享容器和锁定或RW锁定的解决方案,除非非锁定锁定也保护给定正则表达式的操作。万一多重比赛是一个问题,这一切都应该重新思考。