使用OpenMP的线程安全计数器

时间:2017-05-14 07:31:50

标签: openmp c++14

这样做有什么危害的解决方案?

#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <ctime>

int main(){

    int k = 0;
    #pragma omp parallel for 
    for(int i = 0; i < 100000; i++){

        if (i % 2){ /** Conditional based on i **/
            #pragma omp atomic
            k++;

            usleep(1000 * ((float)std::rand() / RAND_MAX));

            #pragma omp task
            std::cout << k << std::endl; /** Some sort of task **/
        }

    }
    return 0;
}

我需要所有k都是唯一的。什么是更好的方法呢?

修改

请注意this question如何引用汇总

特别是我想基于共享变量生成任务。我冒着遇到竞争条件的风险。

考虑线程2完成,对条件求值为true,并在线程1产生所有任务之前递增k。

编辑编辑

我试图强迫竞争条件。没有睡觉就不明显了。事实上存在问题。我怎么能克服这个。

这是一个快速解决方案:

...    
#pragma omp atomic
k++;
int c = k;
...

但我想要保证。

切向。为什么这个实现不起作用?

...
int c;
#pragma omp crtical
{
    k++;
    c = k;
}
...

在函数结束时,std::cout << k;始终小于预期的50000输出proof

1 个答案:

答案 0 :(得分:1)

我不想这么快回答我的问题,但我找到了这个特定实例的解决方案。

从OpenMP 3.1开始,有"atomic capture" pragma

用例就是针对这样的问题。结果代码:

#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <ctime>

int main(){

    int k = 0;
    #pragma omp parallel for 
    for(int i = 0; i < 100000; i++){

        if (i % 2){ /** Conditional based on i **/
            int c;
            #pragma omp atomic capture
            {
                c = k;
                k++;
            }

            usleep(1000 * ((float)std::rand() / RAND_MAX));

            #pragma omp task
            std::cout << c << std::endl; /** Some sort of task **/
        }
    }
    std::cout << k << std::endl; /** Some sort of task **/
    std::cout.flush();
    return 0;
}

如果有人愿意提供想法/代码拱,我会将此问题保持开放。避免这些问题的建议,#pragma omp crtical不起作用的原因