Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何以线程安全的方式在openmp中对全局共享变量的每个进程写入一次?_C++_C_Openmp - Fatal编程技术网

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

C++ 如何以线程安全的方式在openmp中对全局共享变量的每个进程写入一次?,c++,c,openmp,C++,C,Openmp,我想写一个函数 1是线程安全的,即无论是否从openmp并行区域内调用,都可以正常工作 2对全局共享变量执行每个进程一次(不是:每个线程一次)写入 我最初的想法是使用master或single指令,但它们在嵌套并行性方面失败。是否有防故障的解决方案?如果每个进程只写一次,而不是每个线程写一次,那么您不需要任何同步,因为没有任何东西可以与之同步。只需在不受保护的情况下执行写入操作。如果每个进程只执行一次写入操作,而不是每个线程执行一次写入操作,则不需要任何同步操作,因为没有任何同步操作。只需在不受

我想写一个函数

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

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


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

如果每个进程只写一次,而不是每个线程写一次,那么您不需要任何同步,因为没有任何东西可以与之同步。只需在不受保护的情况下执行写入操作。

如果每个进程只执行一次写入操作,而不是每个线程执行一次写入操作,则不需要任何同步操作,因为没有任何同步操作。只需在不受保护的情况下进行写操作。

一种简单的方法是在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;
}
#包括
#包括
void setonce_线程(omp_lock_t*l,int input,int*sharedvar){
如果(omp_测试_锁(l)){
printf(“用%d\n设置锁”,输入);
*sharedvar=输入;
}否则{
printf(“无法设置%d\n”的锁定,输入);
}
}
void setonce_crit(int输入,int*setflag,int*sharedvar){
#pragma-omp-critical
{
如果((*setflag)==0){
(*设置标志)+;
*sharedvar=输入;
printf(“在crit中设置为%d\n”,输入);
}否则{
printf(“无法在带有%d\n”的crit中设置”,输入);
}
}
}
int main()
{
omp_锁定lck;
int sharedvar1,sharedvar2;
int setflag=0;
int输入=17;
omp_集合_嵌套(1);
omp_设置_数量_线程(9);
omp_初始锁定(&lck);
#pragma omp并行共享(lck、sharedvar1、sharedvar2、setflag、input)默认(无)num_线程(3)
{
#pragma omp for

对于(int i=0;i而言,一种粗略的方法是在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;
}
#包括
#包括
void setonce_线程(omp_lock_t*l,int input,int*sharedvar){
如果(omp_测试_锁(l)){
printf(“用%d\n设置锁”,输入);
*sharedvar=输入;
}否则{
printf(“无法设置%d\n”的锁定,输入);
}
}
void setonce_crit(int输入,int*setflag,int*sharedvar){
#pragma-omp-critical
{
如果((*setflag)==0){
(*设置标志)+;
*sharedvar=输入;
printf(“在crit中设置为%d\n”,输入);
}否则{
printf(“无法在带有%d\n”的crit中设置”,输入);
}
}
}
int main()
{
omp_锁定lck;
int sharedvar1,sharedvar2;
int setflag=0;
int输入=17;
omp_集合_嵌套(1);
omp_设置_数量_线程(9);
omp_初始锁定(&lck);
#pragma omp并行共享(lck、sharedvar1、sharedvar2、setflag、input)默认(无)num_线程(3)
{
#pragma omp for
对于(int i=0;我认为OPs的问题是如何安排每个流程只做一次。我认为OPs的问题是如何安排每个流程只做一次。