繁体   English   中英

OpenMP共享数据

[英]OpenMP shared data

我对OpenMP有点新,但总体上有并行处理的经验。 之前我使用过boost::threads ,现在我正在使用openmp进行测试。

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

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

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

我在openmp循环中创建了这个列表(包含正则表达式的向量)私有,因此每个线程都有它自己的列表副本。

问题出现了:

为了显着提高我的应用程序的性能,我需要能够在匹配字符串时从该向量中删除(regex-)项目。

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

所以我把这个列表作为openmp循环中的共享数据对象,但是现在当我尝试将(vector.erase(item#))写入列表时,我在运行时会出现分段错误。

使用boost :: threads我会在写/读它时使用互斥锁来锁定这个对象。

但是openmp似乎处理了大部分同步本身,所以现在我想知道在使用openmp这个问题时处理这个问题的正确方法是什么。

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

#pragma omp critical的好处是简单性和在已知并行区域由单个线程执行时忽略pragma的能力。 缺点仅适用于单个并行区域,并且在该区域内具有全局效果:没有其他线程可以执行该区域中的任何其他关键部分。

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

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

我认为以下内容可能会更好:

  • 您将regex向量保持为私有,并添加相同大小的共享标志向量,以指示某个正则表达式是否仍然有效。
  • 在从私有向量应用某个正则表达式之前,如果此正则表达式未被某个其他线程“擦除”,则代码将检查共享向量。 如果是,则跳过正则表达式。
  • 找到匹配后,代码将与当前正则表达式对应的共享向量的元素标记为“已擦除”,以便从现在开始忽略它。

在这种方案中,存在用于读/写标志的竞赛:在下一个被另一个线程读取为“有效”的时刻,可以将标志设置为“擦除”。 结果,两个不同的线程可以同时找到相同正则表达式的匹配。 但是我认为这个问题存在于当前的解决方案中,其中所有正则表达式容器都是私有的,以及具有共享容器和锁或RW锁的解决方案,除非非RW锁也保护使用给定正则表达式的操作。 如果多个匹配是一个问题,那么应该重新思考。

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

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

编辑:删除了关于'#pragma omp atomic'的部分,因为它无法自动执行所需的操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM