一起来学OpenMP(3)——for循环并行化基本用法

一起来学OpenMP(3)——for循环并行化基本用法

 
一、引言

在“一起来学OpenMP(1)——初体验”中给出了一个for循环并行化的例子,这里做进一步的分析,但本节仅描述for循环并行化的基本用法(即#pragma omp parallel for预处理器指示符),该用法需要满足数据不相关性。

 

二、数据相关性

在循环并行化时,由于多个线程同时执行循环,迭代的顺序是不确定的。如果是数据不相关的,则可以采用基本的#pragma omp parallel for预处理器指示符。

如果语句S2与语句S1相关,那么必然存在以下两种情况之一:

1. 语句S1在一次迭代中访问存储单元L,而S2在随后的一次迭代中访问统一存储单元,称之为循环迭代相关(Loop-Carried Dependence);

2. S1和S2在同一循环迭代中访问统一存储单元L,但S1的执行在S2之前,称之为非循环迭代相关(Loop-Independent Dependence)。

 

三、for循环并行化的几种声明形式

 

[cpp]   view plain copy print ?
  1. #include <iostream>   
  2. #include <omp.h> // OpenMP编程需要包含的头文件   
  3.   
  4. int main()  
  5.  
  6. //for循环并行化声明形式1   
  7. #pragma omp parallel    
  8.      
  9. #pragma omp for    
  10.         for (int 0; 10; ++i)  
  11.          
  12.             std::cout << << std::endl;  
  13.          
  14.      
  15.   
  16. //for循环并行化声明形式2   
  17. #pragma omp parallel for   
  18.     for (int 0; 10; ++j)  
  19.      
  20.         std::cout << << std::endl;  
  21.      
  22.     return 0;  
  23.  

上边代码的两种声明形式是一样的,很显然第二种声明形式更为简洁紧凑。

但是第一种声明形式有一个好处,即可以在并行区域内、for循环以外写其他并行代码。

例如:

 

[cpp]   view plain copy print ?
  1. #include <iostream>   
  2. #include <omp.h> // OpenMP编程需要包含的头文件   
  3.   
  4. int main()  
  5.  
  6. //for循环并行化声明形式1   
  7. #pragma omp parallel    
  8.      
  9.         std::cout << "OK" << std::endl;  
  10. #pragma omp for    
  11.         for (int 0; 10; ++i)  
  12.          
  13.             std::cout << << std::endl;  
  14.          
  15.      
  16.   
  17. //for循环并行化声明形式2   
  18. #pragma omp parallel for   
  19.       
  20.     for (int 0; 10; ++j)  
  21.      
  22.         std::cout << << std::endl;  
  23.      
  24.     return 0;  
  25.  

 

四、for循环并行化的约束条件

尽管OpenMP可以方便地对for循环进行并行化,但并不是所有的for循环都可以进行并行化。以下几种情况不能进行并行化:

1. for循环中的循环变量必须是有符号整形。例如,for (unsigned int i = 0; i < 10; ++i){}会编译不通过;

2. for循环中比较操作符必须是<, <=, >, >=。例如for (int i = 0; i != 10; ++i){}会编译不通过;

3. for循环中的第三个表达式,必须是整数的加减,并且加减的值必须是一个循环不变量。例如for (int i = 0; i != 10; i = i + 1){}会编译不通过;感觉只能++i; i++; --i; 或i--;

4. 如果for循环中的比较操作为<或<=,那么循环变量只能增加;反之亦然。例如for (int i = 0; i != 10; --i)会编译不通过;

5. 循环必须是单入口、单出口,也就是说循环内部不允许能够达到循环以外的跳转语句,exit除外。异常的处理也必须在循环体内处理。例如:若循环体内的break或goto会跳转到循环体外,那么会编译不通过。

 

五、基本for循环并行化举例

 

[cpp]   view plain copy print ?
  1. #include <iostream>   
  2. #include <omp.h> // OpenMP编程需要包含的头文件   
  3.   
  4. int main()  
  5.  
  6.     int a[10] {1};  
  7.     int b[10] {2};  
  8.     int c[10] {0};  
  9.   
  10. #pragma omp parallel    
  11.      
  12. #pragma omp for    
  13.         for (int 0; 10; ++i)  
  14.          
  15.             // c[i]只跟a[i]和b[i]有关   
  16.             c[i] a[i] b[i];  
  17.          
  18.      
  19.   
  20.     return 0;  
  21.  

 

 

六、嵌套for循环

 

[cpp]   view plain copy print ?
  1. #include <iostream>   
  2. #include <omp.h> // OpenMP编程需要包含的头文件   
  3.   
  4. int main()  
  5.  
  6.     int a[10][5] {1};  
  7.     int b[10][5] {2};  
  8.     int c[10][5] {0};  
  9.   
  10. #pragma omp parallel    
  11.      
  12. #pragma omp for    
  13.         for (int 0; 10; ++i)  
  14.          
  15.             for (int 0; 5; ++j)  
  16.              
  17.                 // c[i][j]只跟a[i][j]和b[i][j]有关   
  18.                 c[i][j] a[i][j] b[i][j];  
  19.              
  20.          
  21.      
  22.   
  23.     return 0;  
  24.  

编译器会让第一个cpu完成:

 

[cpp]   view plain copy print ?
  1. for (int 0; 5; ++i)  
  2.  
  3.     for (int 0; 5; ++j)  
  4.      
  5.         // c[i][j]只跟a[i][j]和b[i][j]有关   
  6.                 c[i][j] a[i][j] b[i][j];  
  7.      
  8.  

会让第二个cpu完成:

 

[cpp]   view plain copy print ?
  1. for (int 5; 10; ++i)  
  2.  
  3.     for (int 0; 5; ++j)  
  4.      
  5.         // c[i][j]只跟a[i][j]和b[i][j]有关   
  6.                 c[i][j] a[i][j] b[i][j];  
  7.      
  8.  

 

 

七、小节

本节首先给出了数据相关的概念,然后对基本for循环并行化方法进行了描述,并指出了

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值