OpenMP 并行 for 循环异常

Posted

技术标签:

【中文标题】OpenMP 并行 for 循环异常【英文标题】:OpenMP parallel for loop exceptions 【发布时间】:2022-01-19 01:56:15 【问题描述】:

我对使用 OpenMP 和 *** 还很陌生,如果这是一个愚蠢的问题,我深表歉意!

我正在尝试设置一个大型二维向量来测试我的 CUDA 程序。这些大向量的创建是通过遍历给定维度的所有值(存储在它们自己的向量中)并在新向量中创建一行来完成的,涵盖所有可能的排列。显然,随着维度数量的增加,执行此操作所需的时间呈指数增长,因此我希望将其并行化。

最初我认为问题可能是 OpenMP 和 Thrust 库 host_vectors 之间的不兼容,所以我切换到使用法线向量,问题仍然存在。这是完整的功能:

thrust::host_vector<thrust::host_vector<float>> parallel_create_search_grid(
    thrust::host_vector<float> d1,
    thrust::host_vector<float> d2,
    thrust::host_vector<float> d3,
    thrust::host_vector<float> d4) 

    std::vector<std::vector<float>> final2;

#pragma omp parallel shared(d1, d2, d3, d4, final2)
    
        int j, k, l;
        std::vector<float> temp(4);
        thrust::host_vector<float> h_temp;

#pragma omp for
        for (int i = 0; i < d1.size(); i++)
        

            for (j = 0; j < d1.size(); j++)
            
                for (k = 0; k < d1.size(); k++)
                
                    for (l = 0; l < d1.size(); l++)
                    
                        temp[0] = d1[i];
                        temp[1] = d2[j];
                        temp[2] = d3[k];
                        temp[3] = d4[l];

                        std::cout << i << "," << j << "," << k << "," << l << std::endl;

                        final2.push_back(temp);
                    
                
            
        
    
    return final2;

它不会立即中断,它会在抛出异常之前打印出许多迭代,给我以下信息:

抛出异常:读取访问冲突。 this->_Myproxy 是 0xFFFFFFFFFFFFFFFF.

异常的来源是xmemory中的以下函数,但它的含义是我无法理解的:

_CONSTEXPR20_CONTAINER void _Container_base12::_Swap_proxy_and_iterators_unlocked(_Container_base12& _Right) noexcept 
    _Container_proxy* _Temp = _Myproxy;
    _Myproxy                = _Right._Myproxy;
    _Right._Myproxy         = _Temp;

    if (_Myproxy) 
        _Myproxy->_Mycont = this;
    

    if (_Right._Myproxy) 
        _Right._Myproxy->_Mycont = &_Right;
    

任何帮助将不胜感激。谢谢!

【问题讨论】:

【参考方案1】:

您的问题在于“final2.push_back(temp)”行。您有多个线程推回同一个向量。这是不可能的。在循环之前创建向量,然后写入其中的显式位置。

一般来说,尽量避免push_back,因为它有性能问题。如果您知道向量的大小,请使用该大小创建它。科学应用几乎不需要push_back 的动态性。

【讨论】:

非常感谢,已经创建的向量上的每次迭代的唯一标识符解决了所有问题!我认为你是对的,我可能过于依赖 push_back。我认为我有很多关于内存优化的知识,尽管使用 20 个线程需要约 0.5 倍的串行函数时间。

以上是关于OpenMP 并行 for 循环异常的主要内容,如果未能解决你的问题,请参考以下文章

openMP 嵌套并行 for 循环与内部并行 for

如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?

OpenMP/C++:并行 for 循环,之后减少 - 最佳实践?

openmp 条件并行循环

openmp 条件并行循环

OpenMP 无法使用映射迭代器并行化 for 循环