代码之家  ›  专栏  ›  技术社区  ›  Michael

openmp并行循环的输出容器

  •  0
  • Michael  · 技术社区  · 7 年前

    收集输出容器时,哪个临界截面样式更好?

    // Insert into the output container one object at a time.
    vector<float> output;
    #pragma omp parallel for
    for(int i=0; i<1000000; ++i)
    {
        float value = // compute something complicated
        #pragma omp critical
        {
            output.push_back(value);
        }
    }
    

    // Insert object into per-thread container; later aggregate those containers.
    vector<float> output;
    #pragma omp parallel
    {
        vector<float> per_thread;
        #pragma omp for
        for(int i=0; i<1000000; ++i)
        {
            float value = // compute something complicated
            per_thread.push_back(value);
        }
        #pragma omp critical
        {
            output.insert(output.end(), per_thread.begin(), per_thread.end());
        }
    }
    

    // Insert into the output container one object at a time.
    vector<float> output;
    #pragma omp parallel for
    for(int i=0; i<1000000; ++i)
    {
        int k = // compute number of items
        for( int j=0; j<k; ++j)
        {
            float value = // compute something complicated
            #pragma omp critical
            {
                output.push_back(value);
            }
        }
    }
    

    // Insert object into per-thread container; later aggregate those containers.
    vector<float> output;
    #pragma omp parallel
    {
        vector<float> per_thread;
        #pragma omp for
        for(int i=0; i<1000000; ++i)
        {
            int k = // compute number of items
            for( int j=0; j<k; ++j)
            {
                float value = // compute something complicated
                per_thread.push_back(value);
            }
        }
        #pragma omp critical
        {
            output.insert(output.end(), per_thread.begin(), per_thread.end());
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Zulan    7 年前

    如果每次并行迭代都只插入一项,那么正确的方法是:

    std::vector<float> output(1000000);
    #pragma omp parallel for
    for(int i=0; i<1000000; ++i)
    {
        float value = // compute something complicated
        output[i] = value;
    }
    

    指定的不同元素是线程安全的 std::vector (这是有保证的,因为 i 是不同的)。在这种情况下,没有明显的虚假分享。

    如果您没有在每个并行迭代中插入一个项目,那么两个版本基本上都是正确的。

    您的第一个版本使用 critical 在循环中可能会非常慢-请注意,如果计算非常慢,则总体上可能仍然很好。