对于if-else,increment,如何为OpenMP中任意数量的线程获得相同的并行输出?

Posted

技术标签:

【中文标题】对于if-else,increment,如何为OpenMP中任意数量的线程获得相同的并行输出?【英文标题】:How to get same output for parallelization for any number of threads in OpenMP for if-else, increment? 【发布时间】:2019-01-08 04:58:43 【问题描述】:

我想在没有任何 atomic 操作或 critical 部分的情况下并行化以下代码。

下面给出了我的代码,我已经尝试过但没有预期结果。对于任意数量的线程,我想要相同的输出,其中输出顺序可能不同,即使用 1 个线程的第 5 行可能出现在第 8 行,而使用 4 个线程。如果我没记错的话,这里的临界区是 k++ 区域。请建议我如何在 OpenMP 中做到这一点而不使用关键/原子类子句。

#include <iostream>
#include <vector>
#include "omp.h"
#include "cstdlib"
using namespace std;
int main(int argc, char *argv[])
    int t = atoi(argv[1]);
    vector<int> A0,3,5,7;
    vector<int> B1,2,3,0,3,0,3,0,1,2;
    int k = 0, j;
    for(int i = 0; i<A.size(); i++)
        k = A[i];
        #pragma omp parallel for schedule(static) num_threads(t)
        for(j = 0; j < A.size(); j++)
        if(j == B[k])
            printf("i(yes):%d # B[%d] = %d, thread = %d\n",i, k, B[k], omp_get_thread_num());
            if(k < B.size() && k < A[i+1])
                k++;
            
        else
            printf("i(no):%d # j = %d, k = %d, thread =  %d\n",i, j, k, omp_get_thread_num());
        
    

return 0;

` 当我使用 1 个线程运行时,我得到以下输出:

$ ./a.out 1
i(no):0 # j = 0, k = 0, thread =  0
i(yes):0 # B[0] = 1, thread = 0
i(yes):0 # B[1] = 2, thread = 0
i(yes):0 # B[2] = 3, thread = 0
i(yes):1 # B[3] = 0, thread = 0
i(no):1 # j = 1, k = 4, thread =  0
i(no):1 # j = 2, k = 4, thread =  0
i(yes):1 # B[4] = 3, thread = 0
i(yes):2 # B[5] = 0, thread = 0
i(no):2 # j = 1, k = 6, thread =  0
i(no):2 # j = 2, k = 6, thread =  0
i(yes):2 # B[6] = 3, thread = 0
i(yes):3 # B[7] = 0, thread = 0
i(no):3 # j = 1, k = 7, thread =  0
i(no):3 # j = 2, k = 7, thread =  0
i(no):3 # j = 3, k = 7, thread =  0

但是当我使用 2 个线程运行时,我得到以下不同步和预期的输出。

$ ./a.out 2
i(no):0 # j = 0, k = 0, thread =  0
i(yes):0 # B[0] = 1, thread = 0
i(no):0 # j = 2, k = 0, thread =  1
i(no):0 # j = 3, k = 1, thread =  1
i(no):1 # j = 2, k = 3, thread =  1
i(no):1 # j = 3, k = 3, thread =  1
i(yes):1 # B[3] = 0, thread = 0 
i(no):1 # j = 1, k = 4, thread =  0
i(no):2 # j = 2, k = 5, thread =  1
i(no):2 # j = 3, k = 5, thread =  1
i(yes):2 # B[5] = 0, thread = 0 
i(no):2 # j = 1, k = 6, thread =  0
i(yes):3 # B[7] = 0, thread = 0
i(no):3 # j = 2, k = 7, thread =  1
i(no):3 # j = 3, k = 7, thread =  1
i(no):3 # j = 1, k = 7, thread =  0

【问题讨论】:

【参考方案1】:

你不能并行化你的循环,不管有没有原子。由于迭代j + 1k 的值取决于迭代j 中发生的情况,因此迭代必须按顺序运行。 (问问自己如果j == 1 迭代还没有增加k,那么j == 2 的迭代如何才能正常运行?)

您当前的代码在k 上存在竞争,当它被另一个线程更新时,它的值可能会在迭代中间发生变化。

【讨论】:

以上是关于对于if-else,increment,如何为OpenMP中任意数量的线程获得相同的并行输出?的主要内容,如果未能解决你的问题,请参考以下文章

我应该如何为具有两个范围条件的查询建立索引?

Reportlab:如何为 pdf 文件添加页脚

Javascript 中多个条件的 If-Else 语句

如何为 spark-csv 提供 parserLib 和 inferSchema 选项

如何为公钥固定(SSL 固定)生成 iOS 证书

4.如何为Hive集成RedHat7的OpenLDAP认证