【问题标题】:OpenMP Ordered ParallelizationOpenMP 有序并行化
【发布时间】:2011-08-08 15:54:52
【问题描述】:

我正在尝试并行化以下函数(伪代码):

vector<int32> out;
for (int32 i = 0; i < 10; ++i)
{
    int32 result = multiplyStuffByTwo(i);

    // Push to results
    out.push_back(result);
}

当我现在并行化 for 循环并将 push_back 部分定义为关键路径时,我遇到的问题是(当然)结果的输出顺序并不总是正确的。如何让线程运行在 for 循环的最后一行以正确的顺序执行代码?谢谢!

【问题讨论】:

    标签: c++ openmp parallel-processing


    【解决方案1】:

    你可以通过调用out.resize()来设置out-vector的大小,然后通过索引设置值,而不是push_back()

    伪代码:

    vector<int32> out; out.resize(10);
    for (int32 i = 0; i < 10; ++i)
    {
       int32 result = multiplyStuffByTwo(i);
    
       // set the result
       out[i] = result;
    }
    

    但是,我建议使用“经典”数组。它们的速度要快得多,而且管理起来并不难

    【讨论】:

    • 谢谢!我今天就试试——使用vector时,是否需要在写进程上设置线程锁(临界区)?
    • 其实,一般来说vector类不是线程安全的。这就是为什么 push_back() 是非常有问题的。但在这种情况下,我预计不会有任何问题。再一次:更好地使用普通数组进行此类简单操作(如果您不需要可调整大小的容器)
    • 为什么您希望“经典”数组更快,一旦您将调整大小移出循环?它们应该是相同的。
    • 你说得对,我想,当索引超出范围时,operator[] 会抛出异常。但只有 at() 抛出。所以,这里实际上不应该有任何性能问题。
    • 所以新问题是现在循环变慢了,因为(我认为)每次写入输出时,其他核心的缓存都失效了。我可以考虑为每个线程使用一个私有输出,然后将其交错,但 OpenMP 只允许使用 */+/- 之类的原始操作进行缩减,但不允许分配。有人对此有提示吗?谢谢!
    【解决方案2】:
    vector<int32> out;
    
    #pragma omp parallel for ordered 
    for (int32 i = 0; i < 10; ++i)
    {
        int32 result = multiplyStuffByTwo(i); // this will be run in parallel
    
        #pragma omp ordered
        // Push to results
        out.push_back(result); // this will be run sequential
    }
    

    这可能会有所帮助:

    http://openmp.org/mp-documents/omp-hands-on-SC08.pdf

    【讨论】:

    • -1:如果添加该编译指示,则会失去并行化,这就是重点。
    • 谢谢,我之前也检查过,由于需要线程处理,执行时间增加了。
    • @Jørgen Fogh:对,我更正了 sn-p;现在,只有向量运算是串行的,multiplyStuffByTwo 是并行完成的。如果这个操作会持续很长时间,你应该在这里获得收益。
    猜你喜欢
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 2013-01-06
    • 2016-04-17
    • 2013-12-08
    • 2015-08-18
    • 1970-01-01
    相关资源
    最近更新 更多