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
private
和firstprivate
都可以指定作为线程私有副本的变量,但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)
^~~