OMP 在使用 omp Critical 时会导致内存相关的错误,但在使用 omp Ordered 时不会导致内存相关错误

问题描述 投票:0回答:1

我在 OpenMP 中遇到了一个奇怪的错误。运行程序时,我收到 sigkill 或 sig abort。但有时程序也会成功。

sig Kill 或 sig abort 可能发生在多个地方。有时会出现超出范围的错误。

它看起来像是一场数据竞赛,但运行 valgrind --tool=helgrind 或 drd 不会带来很多信息。我怀疑运行 helgrind 时它甚至会崩溃。

预期结果:关键和有序都应该有效。应该只有速度差异。这是一些细节

1)只有在 Linux 中使用 gnu 编译时才会发生这种情况。在Windows下用MSVC编译的程序没有问题。 使用的命令是

g+= -o -std=c++17 -Wall -fopenmp -O2 -g -fno-var-tracking

2)这似乎是由于 omp 关键而发生的。当我用订购的 omp 替换它时,问题就消失了。

  1. 我可以获得 sigkill 或 sig abort 的地方似乎有所不同。所以我什至无法确定出了什么问题。

  2. helgrind 报告了数据竞争,但它们是这样的

    ==2191== 线程 #1 在 0x837BF50 处写入大小 4 时可能出现数据争用 ==2191== 持有的锁:无 ==2191==位于0x5583F92:??? (在/usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0中) ==2191== 0x55823A1:??? (在/usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0中) ==2191== by 0x5578ED9:GOMP_parallel(在/usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0中)

下面是我的代码的简化示例

calc(
    vector<DataObj>& outputs,
    vector<DataObj>& inputs,
    ) 
{
    omp_set_dynamic(0);
    omp_set_nested(0);
    int rc = 1;
    int maxThreads = omp_get_max_threads();

    const int nProperties = static_cast<int>(inputs.size());
    #pragma omp parallel for schedule(static) \
    shared(outputs,inputs,maxThreads) reduction(&:rc) \
    num_threads(nProperties < maxThreads ? nProperties : maxThreads)
    for (int projN = 0; projN < nProperties; ++projN)
    {
        
        DataObj* projectResults = &(outputs.at(projN));
        
        Calculator* calculator = nullptr;

        #pragma omp critical
        {

        calculator = new Calculator(inputs[projN]);
        
        }
        {
        // resultHolder does most of its work in destructor, important to keep the braces for scope control
        Allocator::Project resultsHolder(projectResults);
        rc &= calculator->calc(
            projectResults);
        }

    delete calculator;
}
return rc;

}

c++ openmp gnu
1个回答
0
投票

示例代码调整:

  • 使用
    omp critical
    来保护对共享资源的访问,或考虑使用
    omp ordered
    等替代方案或针对不同行为的其他同步机制。
  • 研究并行区域内动态分配的使用并确保正确同步以防止数据争用。
#pragma omp parallel for schedule(static) shared(outputs,inputs,maxThreads) reduction(&:rc) num_threads(nProperties < maxThreads ? nProperties : maxThreads)
for (int projN = 0; projN < nProperties; ++projN) {
    DataObj* projectResults = &(outputs.at(projN));
    Calculator* calculator = nullptr;

    #pragma omp critical
    {
        calculator = new Calculator(inputs[projN]);
    }
    // Scope for resultHolder to ensure destructor is called before calculator deletion
    {
        Allocator::Project resultsHolder(projectResults);
        rc &= calculator->calc(projectResults);
    }
    delete calculator;
}
© www.soinside.com 2019 - 2024. All rights reserved.