首页 > 解决方案 > std::lock_guard 和 #pragma omp critical 之间的区别

问题描述

让我们考虑一些代码来安全地在具有多个线程的for循环中递增变量。

为了实现这一点,您必须在增加变量时使用某种锁定机制。当我在寻找解决方案时,我想出了以下解决方案。

我的问题是:

  1. 它们同样好还是其中一个有一些后备?
  2. 何时使用 amutex而不是#pragma omp critical
#include <iostream>
#include <mutex>

int main(int argc, char** argv)
{
    int someVar = 0;
    std::mutex someVar_mutex;

    #pragma omp parallel for
    for (int i = 0; i < 1000; i++)
    {
        std::lock_guard<std::mutex> lock(someVar_mutex);
        ++someVar;
    }

    std::cout << someVar << std::endl;

    return 0;
}
#include <iostream>

int main(int argc, char** argv)
{
    int someVar = 0;

    #pragma omp parallel for
    for (int i = 0; i < 1000; i++)
    {
        #pragma omp critical
        ++someVar;
    }

    std::cout << someVar << std::endl;

    return 0;
}

标签: c++multithreadingperformanceopenmpmutex

解决方案


临界区与获取锁的目的相同(并且可能会在内部使用锁)。

  1. std::mutex是标准的 C++ 功能,而#pragma omp critical它是 OpenMP 扩展,不是由标准定义的。

  2. 临界区名称对整个程序都是全局的(与模块边界无关)。因此,如果您在多个模块中有同名的临界区,则不能同时执行其中两个。如果省略名称,则假定为默认名称。(文档)。

更喜欢标准 C++,除非有充分的理由使用另一个(在测量两者之后)。

不是直接针对这个问题,但是这个循环还有另一个问题:每次循环迭代都会执行锁。这会显着降低性能(另请参阅此答案)。


推荐阅读