如何在 OpenMP 中使用锁?

Posted

技术标签:

【中文标题】如何在 OpenMP 中使用锁?【英文标题】:How to use lock in OpenMP? 【发布时间】:2011-01-24 16:23:21 【问题描述】:

我有两段 C++ 代码在 2 个不同的内核上运行。他们都写入同一个文件。

如何使用 OpenMP 并确保没有崩溃?

【问题讨论】:

【参考方案1】:

您想要OMP_SET_LOCK/OMP_UNSET_LOCK 函数: https://hpc.llnl.gov/tuts/openMP/#OMP_SET_LOCK

基本上:

omp_lock_t writelock;

omp_init_lock(&writelock);

#pragma omp parallel for
for ( i = 0; i < x; i++ )

    // some stuff
   omp_set_lock(&writelock);
    // one thread at a time stuff
    omp_unset_lock(&writelock);
    // some stuff


omp_destroy_lock(&writelock);

尽管特定的 API 调用不同,但大多数锁定例程(例如 pthreads 信号量和 sysv 信号量)都在这种逻辑上工作。

【讨论】:

【参考方案2】:
#pragma omp critical

    // write to file here

【讨论】:

【参考方案3】:

为了后来者的利益,使用critical 是另一种选择。您甚至可以创建命名的关键部分。

例如:

#include <omp.h>

void myParallelFunction()

    #pragma omp parallel for
    for(int i=0;i<1000;++i)
    

        // some expensive work 

        #pragma omp critical LogUpdate
        
            // critical section where you update file        
        

        // other work

        #pragma omp critical LogUpdate
        
            // critical section where you update file      
        
    
 

编辑:在 Victor Eijkhout 发起的 cmets 中有一个很棒的主题。总结和释义:简而言之,critical 锁定了一个代码段。在您想要做的只是锁定特定数据项的更复杂的示例中,这可能是过度的。在这两种方法之间做出选择之前,了解这一点很重要。

【讨论】:

严重锁定代码段。如果您有数千次迭代并且您只是想确保没有两个线程同时执行相同的迭代,那么这不是一个好主意。使用关键意味着只有一个线程进行任何迭代。命名临界区稍微缓解了这个问题,但锁更灵活,因为它们锁定的是数据元素,而不是代码片段。 @VictorEijkhout 抱歉,我不明白这个解决方案与@user257111 有什么不同。对我来说,用 lock 和 unlock 替换 #pragma omp critical 会在这个例子中得到完全相同的代码,不是吗? @rkioji 最初的问题从未指定需要独占执行的代码是什么,因此很难在这里确定什么是合适的。以数据库为例。使用锁,您可以锁定数据库中的单个项目,以确保没有两个进程同时更新它:锁保护特定的数据项。另一方面,如果您在更新周围放置一个关键部分,您可以确保没有两个进程可以同时执行更新语句,无论它们更新什么。因此,在数据库的情况下,关键部分是多余的。 (达到堆栈溢出限制。) @VictorEijkhout 我同意你的看法。在某些情况下,锁定数据听起来更有效。我想说的是,使用omp critical 或锁定/解锁会导致与此答案中给出的示例相同的性能。 这些是我写这篇文章时没有意识到的重要观点。我已经编辑了答案以进行总结。

以上是关于如何在 OpenMP 中使用锁?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OpenMP 中分叉大量线程?

如何确认多核系统中的openmp是不是使用了所有内核?

如何使用 OpenMP 在 C++ 中实现监视器?

使用编译器内在函数实现自旋锁以同步 OpenMP 线程

如何在makefile中使用OpenMP?

如何使用多线程处理缓存的数据结构(例如 openmp)