无法理解 OpenMP 代码中的一些意外行为

Posted

技术标签:

【中文标题】无法理解 OpenMP 代码中的一些意外行为【英文标题】:Trouble understanding some unexpected behaviour in code with OpenMP 【发布时间】:2019-11-08 22:01:48 【问题描述】:

关于 OpenMP 并行化的问题。我在下面包含了我的函数的精简版本。问题是,for 循环的内容并未针对 uiIndex 的所有值进行评估,尽管并非总是如此。

    我使用缓冲区 vec_succ_status 检查是否所有的 uiIndex 值都得到了评估。事实证明不是。 我的代码没有崩溃,它只是从函数 compute_Lagr_shortest_paths_from_source 中退出,没有遇到下面函数定义中的任何 exit(-1) 语句。 我在 Ubunutu 14 上使用 g++ 7.4.0 版本,每次失败时,都会跳过一个 uiIndex 值。函数无法评估的 uiIndex 没有一致性。 对于我一直在测试的程序,vec_group 的大小始终为 1,因此只有 for 循环中的第一个 if 语句会计算。 在我的主函数中,我包含了 omp_set_num_threads(4) 行。除此之外,我没有为 OpenMP 设置任何其他设置(例如调度程序类型)。 另外,我可以保证没有 2 个 uiIndex 值会导致相同的 uiRobot 值,因此不会有 2 个线程必须在函数的有效期内访问相同的 vec_cf_graphs[uiRobot] 数组。

我想知道我是否对 OpenMp 做出了一些错误的假设。我要求在所有线程之间共享所有对象,例如 vec_cf_graphs、vec_succ_status。我想知道是否需要明确提及它们是共享的,因为它通常是推荐的方法。无论如何,我认为我实施的方式也足够了。但是,对我来说,某些 uiIndex 值可以完全跳过,这似乎很奇怪。我必须指出,我反复调用显示的函数,但只是有时某些 uiIndex 值会从评估中跳过。如果有人可以指出我的方法的潜在问题,那就太好了。我很高兴提供更多信息。谢谢。

bool compute_Lagr_shortest_paths_from_source(std::vector<Robot_CF_Graph>& vec_cf_graphs, const std::vector<std::vector<size_t>>& vec_robot_groups)

    size_t uiIndex;
    std::vector<bool> vec_succ_status(vec_robot_groups.size(), false);

    #pragma omp parallel for default(shared) private(uiIndex)
    for(uiIndex = 0; uiIndex < vec_robot_groups.size(); uiIndex++)
    
        vec_succ_status[uiIndex] = false;
        const auto& vec_group = vec_robot_groups[uiIndex];

        if(1 == vec_group.size())
        
        size_t uiRobot = vec_group[0];
        vec_cf_graphs[uiRobot].compute_shortest_path("ABC"); 
        vec_succ_status[uiIndex] = true;  
        
        else          
                    
        std::cout<< "Tag: Code should not have entered this block"<<endl;
        exit(-1);                       
        

        if(false == vec_succ_status[uiIndex])
        
        std::cout<< "It is not possible for this to happen \n";
        exit(-1);
        
       

    return true;     

【问题讨论】:

也许还值得一提的是,exit(-1) 应该在 parallel for 构造中被避免。我很惊讶编译器没有警告你,因为我记得如果你使用return,它甚至无法编译。 【参考方案1】:

您同时写信给vector&lt;bool&gt;,这不是“正常”vector。它具有内部内存优化。这是未定义的行为。

在此处查看详细推理:

Write concurrently vector<bool>

vector&lt;bool&gt; 与其他vectors 有何不同,请参见此处:

https://en.cppreference.com/w/cpp/container/vector_bool

仅使用vector&lt;char&gt; 与 0 或 1 代表真或假是解决此问题的最简单方法。如果您想拥有更优雅的代码,此处讨论了其他选项:

Alternative to vector<bool>

【讨论】:

以上是关于无法理解 OpenMP 代码中的一些意外行为的主要内容,如果未能解决你的问题,请参考以下文章

使用 pthread 进行锻炼,但我的代码中有一些意外行为

显示意外行为的 tkinter 代码

如果重载和覆盖相同的方法,Java中的意外多态行为

C#意外的属性行为[重复]

读取文件时无法使用 OpenMP 获得加速

我如何理解我在 openMP 中的代码?