简体   繁体   English

OpenMP共享数据

[英]OpenMP shared data

I'm somewhat new to OpenMP but have experience with parallel processing in general. 我对OpenMP有点新,但总体上有并行处理的经验。 I worked with boost::threads before and now I'm testing around with openmp. 之前我使用过boost::threads ,现在我正在使用openmp进行测试。

The problem is that I don't know how to handle shared data access because I don't really know what openmp does internally with shared data objects inside parallel loops. 问题是我不知道如何处理共享数据访问,因为我真的不知道openmp在内部对并行循环内的共享数据对象做了什么。

What I'm doing right now (this is working so far): I read files from disk into memory with mmap. 我现在正在做什么(这是迄今为止的工作):我使用mmap将文件从磁盘读入内存。 I receive a pointer on char after the memory map part. 我在内存映射部分后面收到一个关于char的指针。

OpenMP can now use this pointer inside an OpenMP parallel for loop and share the data between threads. OpenMP现在可以在OpenMP并行for循环中使用此指针,并在线程之间共享数据。 I'm now able to search for regular expression matches inside the mapped and shared file with multiple threads checking every string against a (pretty long) list of regular expressions. 我现在能够在映射和共享文件中搜索正则表达式匹配,多个线程针对(非常长的)正则表达式列表检查每个字符串。

I made this list (a vector containing regex) private inside the openmp loop, so every thread has it's own copy of this list. 我在openmp循环中创建了这个列表(包含正则表达式的向量)私有,因此每个线程都有它自己的列表副本。

Here comes the problem: 问题出现了:

To dramatically increase performance of my application I need to be able to remove (regex-)items from this vector once they match a string. 为了显着提高我的应用程序的性能,我需要能够在匹配字符串时从该向量中删除(regex-)项目。

Now all the other active threads need to have this item removed from their list too asap. 现在所有其他活动线程都需要从列表中删除此项目。

So I made this list a shared data object inside the openmp loop but now I get segmentation faults at runtime when I try to write (vector.erase(item#)) to the list. 所以我把这个列表作为openmp循环中的共享数据对象,但是现在当我尝试将(vector.erase(item#))写入列表时,我在运行时会出现分段错误。

With boost::threads I would just have used a mutex for locking this object while writing/reading it. 使用boost :: threads我会在写/读它时使用互斥锁来锁定这个对象。

But openmp seems to handle most of the synchronization itself so now I wonder what would be the correct approach to handle this problem when using openmp which is new to me. 但是openmp似乎处理了大部分同步本身,所以现在我想知道在使用openmp这个问题时处理这个问题的正确方法是什么。

For synchronization, you may use #pragma omp critical or you may use OpenMP lock routines ( omp_{init,set,unset,destroy}_lock ). 对于同步,您可以使用#pragma omp critical或者您可以使用OpenMP锁定例程( omp_{init,set,unset,destroy}_lock )。

The benefits of #pragma omp critical are simplicity and ability to ignore the pragma when the parallel region is known to execute by a single thread. #pragma omp critical的好处是简单性和在已知并行区域由单个线程执行时忽略pragma的能力。 Drawbacks are applicability only to a single parallel region, and global effect within this region: no other thread can execute any other critical section in the region. 缺点仅适用于单个并行区域,并且在该区域内具有全局效果:没有其他线程可以执行该区域中的任何其他关键部分。

OpenMP lock routines are similar to most other available locks, eg those of pthreads or Boost (RAII aside). OpenMP锁定例程与大多数其他可用锁类似,例如pthreads或Boost(RAII除外)。 You initialize a lock object, then use it to protect certain critical sections, and destroy when it's unnecessary. 您初始化一个锁定对象,然后使用它来保护某些关键部分,并在不必要时销毁它。 These locks can be used to protect access to data from different parallel regions, to build a distributed locking scheme, etc.; 这些锁可用于保护对来自不同并行区域的数据的访问,构建分布式锁定方案等; but certain amount of overhead is always incurred, and surely usage is more "hairy" comparing to #pragma omp critical . 但总会产生一定的开销,与#pragma omp critical相比,肯定使用起来更“毛茸茸”。

However, I would challenge the design of the parallel solution. 但是,我会挑战并行解决方案的设计。 Erasing an element from middle of the vector makes all iterators invalidated, and moves elements. 从向量中间擦除元素会使所有迭代器失效,并移动元素。 Erase is supposedly a rare operation (otherwise, the choice of vector would be questionable even in serial code I think), but due to the above effects you have to protect all reads of the vector too, and that will likely be costly. 擦除被认为是一种罕见的操作(否则,即使在我认为的串行代码中,矢量的选择也会有问题),但由于上述影响,你必须保护矢量的所有读取,这可能是昂贵的。 Read/write locks could give some relief, but those are not available in OpenMP, so you would need to use either platform-specific interfaces or a 3rd party library. 读/写锁可以带来一些缓解,但这些在OpenMP中不可用,因此您需要使用特定于平台的接口或第三方库。

I think the following will potentially work better: 我认为以下内容可能会更好:

  • You keep regex vectors private, and add a same-size shared vector of flags that indicate whether a certain regex is still valid or not. 您将regex向量保持为私有,并添加相同大小的共享标志向量,以指示某个正则表达式是否仍然有效。
  • Before applying a certain regex from a private vector, the code checks in the shared vector if this regex was not "erased" by some other thread. 在从私有向量应用某个正则表达式之前,如果此正则表达式未被某个其他线程“擦除”,则代码将检查共享向量。 If it was, the regex is skipped. 如果是,则跳过正则表达式。
  • After finding a match, the code marks the element of the shared vector that corresponds to the current regex as "erased" so that it will be ignored from now on. 找到匹配后,代码将与当前正则表达式对应的共享向量的元素标记为“已擦除”,以便从现在开始忽略它。

In this scheme, there exist races for reading/writing flags: a flag might be set to "erased" the very next moment it was read as "valid" by another thread. 在这种方案中,存在用于读/写标志的竞赛:在下一个被另一个线程读取为“有效”的时刻,可以将标志设置为“擦除”。 As the result, two different threads may concurrently find a match for the same regex. 结果,两个不同的线程可以同时找到相同正则表达式的匹配。 However this problem I believe exists in your current solution where all regex containers are private, as well as in a solution with a shared container and locks or RW locks, unless a non-RW lock protects also the operation with a given regex. 但是我认为这个问题存在于当前的解决方案中,其中所有正则表达式容器都是私有的,以及具有共享容器和锁或RW锁的解决方案,除非非RW锁也保护使用给定正则表达式的操作。 In case multiple matches are a problem, it all should be re-thought. 如果多个匹配是一个问题,那么应该重新思考。

You can achieve this by creating a critical section. 您可以通过创建关键部分来实现此目的。

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

EDIT: Removed the part about '#pragma omp atomic' as it cannot atomically perform the operations needed. 编辑:删除了关于'#pragma omp atomic'的部分,因为它无法自动执行所需的操作。

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

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