一起来学OpenMP(3)——for循环并行化基本用法
2013-09-10 17:54
274 查看
一起来学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 plaincopyprint?
#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件
int main()
{
//for循环并行化声明形式1
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < 10; ++i)
{
std::cout << i << std::endl;
}
}
//for循环并行化声明形式2
#pragma omp parallel for
for (int j = 0; j < 10; ++j)
{
std::cout << j << std::endl;
}
return 0;
}
上边代码的两种声明形式是一样的,很显然第二种声明形式更为简洁紧凑。
但是第一种声明形式有一个好处,即可以在并行区域内、for循环以外写其他并行代码。
例如:
[cpp] view plaincopyprint?
#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件
int main()
{
//for循环并行化声明形式1
#pragma omp parallel
{
std::cout << "OK" << std::endl;
#pragma omp for
for (int i = 0; i < 10; ++i)
{
std::cout << i << std::endl;
}
}
//for循环并行化声明形式2
#pragma omp parallel for
for (int j = 0; j < 10; ++j)
{
std::cout << j << std::endl;
}
return 0;
}
四、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 plaincopyprint?
#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件
int main()
{
int a[10] = {1};
int b[10] = {2};
int c[10] = {0};
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < 10; ++i)
{
// c[i]只跟a[i]和b[i]有关
c[i] = a[i] + b[i];
}
}
return 0;
}
六、嵌套for循环
[cpp] view plaincopyprint?
#include <iostream>
#include <omp.h> // OpenMP编程需要包含的头文件
int main()
{
int a[10][5] = {1};
int b[10][5] = {2};
int c[10][5] = {0};
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < 10; ++i)
{
for (int j = 0; j < 5; ++j)
{
// c[i][j]只跟a[i][j]和b[i][j]有关
c[i][j] = a[i][j] + b[i][j];
}
}
}
return 0;
}
编译器会让第一个cpu完成:
[cpp] view plaincopyprint?
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < 5; ++j)
{
// c[i][j]只跟a[i][j]和b[i][j]有关
c[i][j] = a[i][j] + b[i][j];
}
}
会让第二个cpu完成:
[cpp] view plaincopyprint?
for (int i = 5; i < 10; ++i)
{
for (int j = 0; j < 5; ++j)
{
// c[i][j]只跟a[i][j]和b[i][j]有关
c[i][j] = a[i][j] + b[i][j];
}
}
七、小节
本节首先给出了数据相关的概念,然后对基本for循环并行化方法进行了描述,并指出了
相关文章推荐
- 一起来学OpenMP(3)——for循环并行化基本用法
- 一起来学OpenMP(3)——for循环并行化基本用法
- for循环的基本用法
- swift基本用法-for循环遍历,遍历字典,循环生成数组
- linux笔记 第五天 vim基本用法、bash编程初步和for循环
- 浅析 - TabLayout的基本用法
- SAXBuilder基本用法
- UI手势的基本用法
- jquery validate.js表单验证的基本用法入门
- HTML5中 基本用法及属性 韩俊强的博客
- My97DatePicker基本用法
- CheckBox的基本用法
- Konva基本用法
- smarty的基本用法
- std:move基本用法和理解
- Jquery EasyUI后台基本用法总结
- 【python】redis基本命令和基本用法详解
- AfxBeginThread的基本用法
- django中urls和views的基本用法