如何使用openMP的数据环境——private、firstprivate和default

openMP的数据环境


0 上菜

// omp_atomic.cpp
// compile with: /openmp
#include <stdio.h>
#include <omp.h>

#define DEMO_ID 1

unsigned int var;
unsigned int buf[3] = {
    
    1,2,3};

int main{
    
    

#if(DEMO_ID == 0) // threads ops
-
#elif(DEMO_ID == 1) // data env
    var = 7;
    #pragma omp parallel num_threads(3) firstprivate(var, buf) default(none)
    {
    
    
        for(int i=0;i<3;i++){
    
    
            printf("thread %d - buffer[%d] = %d\n", omp_get_thread_num(), i, buf[i]);
            printf("thread %d - var = %d\n", omp_get_thread_num(), var);
        }
    }
#endif
    return 0;
}

1 菜谱

1.1 划定并行区域

使用编译参数#pragma omp parallel划定并行执行的代码区域

    #pragma omp parallel num_threads(3) firstprivate(var, buf) default(none)
    {
    
    
        for(int i=0;i<3;i++){
    
    
            printf("thread %d - buffer[%d] = %d\n", omp_get_thread_num(), i, buf[i]);
            printf("thread %d - var = %d\n", omp_get_thread_num(), var);
        }
    }
  • 使用num_threads(3)指明三个线程并行(做一样的事情)
  • 使用firstprivate(var, buf)指定每个线程都私有变量var和数组buf的副本(并用原有初始值初始化)
  • 使用default(none)指明要求编译时检查所有变量的私有属性,有变量未被指明属性则报错

1.2 打印关键信息

  • 使用omp_get_thread_num()获取线程id

1.3 运行结果

上述代码运行结果:

thread 1 - buffer[0] = 1
thread 1 - var = 7
thread 1 - buffer[1] = 2
thread 1 - var = 7
thread 1 - buffer[2] = 3
thread 1 - var = 7
thread 2 - buffer[0] = 1
thread 2 - var = 7
thread 2 - buffer[1] = 2
thread 2 - var = 7
thread 2 - buffer[2] = 3
thread 2 - var = 7
thread 0 - buffer[0] = 1
thread 0 - var = 7
thread 0 - buffer[1] = 2
thread 0 - var = 7
thread 0 - buffer[2] = 3
thread 0 - var = 7

可以看到,三个线程执行同样的操作,var和buf的初始值与原有初始值一致。

2 比较

2.1 private

privatefirstprivate都可以指定作为线程私有副本的变量,但private指定的变量不会用原有初始值初始化。若修改程序为:

    #pragma omp parallel num_threads(3) private(var, buf) default(none)
    {
    
    
        for(int i=0;i<3;i++){
    
    
            printf("thread %d - buffer[%d] = %d\n", omp_get_thread_num(), i, buf[i]);
            printf("thread %d - var = %d\n", omp_get_thread_num(), var);
        }
    }

则输出为:

thread 0 - buffer[0] = 0
thread 0 - var = 8
thread 0 - buffer[1] = 16
thread 0 - var = 8
thread 0 - buffer[2] = 0
thread 0 - var = 8
thread 2 - buffer[0] = 0
thread 2 - var = 16478712
thread 2 - buffer[1] = 16477976
thread 2 - var = 16478712
thread 2 - buffer[2] = 0
thread 2 - var = 16478712
thread 1 - buffer[0] = 0
thread 1 - var = 16477560
thread 1 - buffer[1] = 16476728
thread 1 - var = 16477560
thread 1 - buffer[2] = 0
thread 1 - var = 16477560

可见初始值不确定。

2.2 default

default用于辅助指定变量的私有属性,通常使用default(none)来要求所有变量都必须显式使用private等语句指定该类属性。若从private列表中删除var,将程序修改成如下形式:

    #pragma omp parallel num_threads(3) private(buf) default(none)
    {
    
    
        for(int i=0;i<3;i++){
    
    
            printf("thread %d - buffer[%d] = %d\n", omp_get_thread_num(), i, buf[i]);
            printf("thread %d - var = %d\n", omp_get_thread_num(), var);
        }
    }

则编译时报错:

.\main.c: In function 'main':
.\main.c:58:13: error: 'var' not specified in enclosing 'parallel'
             printf("thread %d - var = %d\n", omp_get_thread_num(), var);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.\main.c:54:13: error: enclosing 'parallel'
     #pragma omp parallel num_threads(3) private( buf) default(none)
             ^~~

3 参考

猜你喜欢

转载自blog.csdn.net/qq_33904382/article/details/130795195