c++ - 如何以线程安全的方式在 openmp 中实现每个进程一次写入全局共享变量?

标签 c++ c openmp

我想写一个函数

1 是线程安全的,即无论是否从 openmp 并行区域内调用都能正常工作,

2 执行每个进程一次(不是:每个线程一次)写入全局共享变量。

我最初的想法是使用 mastersingle 指令,但它们在嵌套并行性方面失败了。是否有防故障解决方案?

最佳答案

一种粗略的方法是在 OpenMP 临界区中,您都在其中设置“已设置”标志和共享变量。当每个线程进入临界区时,它会测试已经设置的标志,并且

更细粒度的方法是使用 OpenMP 锁;你可以让第一个线程通过设置锁,之后其他线程不能,并将其用作你的标志:

#include <stdio.h>
#include <omp.h>

void setonce_thread(omp_lock_t *l, int input, int *sharedvar) {
    if (omp_test_lock(l)) {
        printf("Set lock with %d\n", input);
        *sharedvar = input;
    } else {
        printf("Could not set lock with %d\n", input);
    }
}

void setonce_crit(int input, int *setflag, int *sharedvar) {
#pragma omp critical
    {
        if ((*setflag) == 0) {
            (*setflag)++;
            *sharedvar = input;
            printf("Set in crit with %d\n", input);
        } else {
            printf("Could not set in crit with %d\n", input);
        }
    }
}


int main()
{
    omp_lock_t lck;
    int sharedvar1, sharedvar2;
    int setflag = 0;
    int input = 17;

    omp_set_nested(1);
    omp_set_num_threads(9);
    omp_init_lock(&lck);
#pragma omp parallel shared(lck, sharedvar1, sharedvar2, setflag, input) default(none) num_threads(3)
    {
#pragma omp for
        for (int i=0; i<3; i++) {
#pragma omp parallel shared(lck, sharedvar1, sharedvar2, setflag, input) default(none) 
            {
#pragma omp for
                for (int j=0; j<3; j++) {
                    int id=omp_get_thread_num();
                    setonce_thread(&lck, id, &sharedvar1);
                    setonce_crit(id, &setflag, &sharedvar2);
                }
            }
        }
        omp_unset_lock(&lck);
    }
    omp_destroy_lock(&lck);

    printf("Shared Var 1 = %d\n", sharedvar1);
    printf("Shared Var 2 = %d\n", sharedvar2);
    printf("Set Flag     = %d\n", setflag);
    return 0;
}

关于c++ - 如何以线程安全的方式在 openmp 中实现每个进程一次写入全局共享变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8609405/

相关文章:

c++ - 在 OS X Mavericks 中从 C++ 链接 C

具有其他类数据类型的 C++ 构造函数

计算缓冲区中的实例数失败测试用例

c++ - pi 计算的 OpenMP 并行化速度慢或错误

c++ - 2 插槽系统上的 OpenMP

Clang OpenMP 版本,无法获取最新版本

c++ - C++中 "main"线程的id

c - 使用 IPC 队列发送消息时,标识符已删除 (EIDRM) 错误

c - 一个线程执行多个进程

c++ - 创建一个结构体作为枚举类成员