OpenACC 中parallel 和kernels的区别

Kernels构件

Kernels构件源于PGI Accelerator模型的region构件。嵌套kernels构件里的循环可能会被编译器转换成能在GPU上高效并行的部分。在这个过程中有三步。 

1:判断并行中遇到的循环。

2:把抽象的并行转换成硬件上的并行。对于NVIDIA CUDA GPU, 它会把并行的循环映射到grid层次(blockIdx) 或 thread层次(threadIdx)。OpenACC申明, gang 对应grid, vector 对应thread。编译器可能会通过strip-mining(一种拆分循环利用缓存的技术)把一层的循环映射到多层。

3:编译器生成并优化代码。

 

在kernels构件中,编译器用自动并行技术识别并行的循环。这个识别能被指令(directives)和条款(clauses)增强,比如说loop independent。使用-Minfo标志可以让PGI 编译器显示编译信息。你能看到类似Loop is parallelizable 如果编译器认为这个循环可以被并行化。。

 

在第二步中,PGI编译器使用目标硬件的模型去选择循环被映射成vector并行还是gang。比如说,循环中有多个步进为1的数组时,更多的会被映射成vector(thread)并行。在NVIDIA GPU上,这种映射更倾向于生成能同时运行的代码。同样能用 loop gang 明确生成grid上的并行,或者用loop vector(64)生成64个thread的block。但这会造成移植上的困难。

第三步底层代码生成和优化。

Parallel 构件

Parallel构件源于OpenMp的parallel构件。OpenMP会立即产生很多多余的线程,当运行到一个循环是,一个线程运行一部分。

同样的,OpenACC的parallel构件也会产生多余的gangs。不同的是OpenACC的parallel在结束时没有同步。就像带了nowait参数的OpenMP一样。

Kernels和parallel主要的不同是, 整个parallel构件会被变成一个kernel。比如说在CUDA中,会变成一个kernel<<<grid, block>>>();

 

举例分析:

单个循环

         在单个循环中kernels和parallel几乎一样。

#pragma acc kernels loopfor( i = 0; i < n; ++i )a[i] = b[i] + c[i];

等价于

 #pragma acc kernels{for( i = 0; i < n; ++i )a[i] = b[i] + c[i];}

如果a,b,c是指针的话,编译器没法消除指针的歧义,可能不会生成并行代码。可以用restrict属性/加-Msafeptr(不推荐)/jia independent子语

#pragma acc kernels loop independentfor( i = 0; i < n; ++i )a[i] = b[i] + c[i];

如果用parallel构件,就相当于告诉编译器两件事

  1. 把接下来的循环映射成kernel
  2. 把每一个步长分到gangs(grid)上
#pragma acc parallel loopfor( i = 0; i < n; ++i )a[i] = b[i] + c[i];

这会造成每一个block里都只有一个thread的情况。

下面一种和上面完全一致

 #pragma acc parallel{#pragma acc loopfor( i = 0; i < n; ++i )a[i] = b[i] + c[i];}

但是如果把里面的loop子语去掉

#pragma acc parallel{for( i = 0; i < n; ++i )a[i] = b[i] + c[i];}

循环就会在所有gang中运行。这是另一种浪费。

         嵌套循环:

  !$acc kernels loopdo j = 1, mdo i = 1, na(j,i) = b(j,i) * alpha + c(i,j) * betaenddo
enddo

编译器发现j被更多的数组用作stride-1索引,他会选择把j循环作为vector并行,把i循环作为gangs并行。

但是,编译器在这里有点自由。他可能会生成二维的grid,把i,j作为在gangs中多个block的索引。或者生成二维的block,把i,j作为vector中多个threads的索引。但是他总是寻找好性能的实现。

 !$acc parallel loopdo j = 1, mdo i = 1, na(j,i) = b(j,i) * alpha + c(i,j) * betaenddoenddo

或者

!$acc paralleldo j = 1, m!$acc loopdo i = 1, na(j,i) = b(j,i) * alpha + c(i,j) * betaenddoenddo

这样编译器能把i或j循环转成vector并行。

 !$acc parallel loopdo i = 1, ndo j = 1, ma(j,i) = b(j,i) * alpha + c(i,j) * betaenddoenddo

这样编译器更可能会把i作为gangs并行,j作为vector并行。

不紧凑的嵌套循环(Non-tight Nested Loop)

#pragma acc kernels loopfor( i = 0; i < nrows; ++i ){double val = 0.0;int nstart = rowindex[i];int nend = rowindex[i+1];#pragma acc loop vector reduction(+:val)for( n = nstart; n < nend; ++n )val += m[n] * v[colndx[n]];r[i] = val;}

编译器会为外循环生成gang并行,内循环vector并行

#pragma acc kernels loopfor( i = 0; i < nrows; ++i ){double val = 0.0;int nstart = rowindex[i];int nend = rowindex[i+1];for( n = nstart; n < nend; ++n )val += m[n] * v[colndx[n]];r[i] = val;}

如果没有loop导语, 编译器可能会把外循环在gangs和vector上并行, 或者自动把内循环vector化。

 #pragma acc parallel loopfor( i = 0; i < nrows; ++i ){double val = 0.0;int nstart = rowindex[i];int nend = rowindex[i+1];#pragma acc loop vector reduction(+:val)for( n = nstart; n < nend; ++n )val += m[n] * v[colndx[n]];r[i] = val;}

这样,编译器就不需要分析了。或者可以去掉loop vector reduction而让编译器自动寻找并行的机会。

相邻的循环

 !$acc kernelsdo i = 1, na(i) = mob(i)*charge(i)enddodo i = 2, n-1c(i) = 0.5*(a(i-1) + a(i+1))enddo
!$acc end kernels

这两个循环会被独自的分析,调度和编译。A会在第二个循环开始前结束。这和下面一样。

 !$acc kernels loopdo i = 1, na(i) = mob(i)*charge(i)enddo!$acc kernels loopdo i = 2, n-1c(i) = 0.5*(a(i-1) + a(i+1))enddo

但是,写成parallel构件就会很不同。

!$acc parallel!$acc loopdo i = 1, na(i) = mob(i)*charge(i)enddo!$acc loopdo i = 2, n-1c(i) = 0.5*(a(i-1) + a(i+1))enddo!$acc end parallel

两个循环会同时被并行化,而且没有同步操作。A可能还没完成,第二个循环就开始了。

同样的问题可能会在reduction中出现

 sum = 0.0!$acc kernels!$acc loop reduction(+:sum)do i = 1, nsum = sum + v(i)enddodo i = 1,nv(i) = v(i) / sumenddo!$acc end kernels

因为用的是kernel,第一个规约会在第二个循环开始前结束。

如果写成parallel,这个依赖关系就又破了

   sum = 0.0!$acc parallel!$acc loop reduction(+:sum)do i = 1, nsum = sum + v(i)enddo!$acc loopdo i = 1,nv(i) = v(i) / sumenddo!$acc end parallel

事实上,多数教程都建议不要把reduction 和acc loop parallel 一起用。

总结:

         Kernels 和parallel构件都用于解决一样的问题。区别是 kernels构件更隐含一些,给编译器更多的自由性选择。Parallel更加严格,需要程序员更多的分析。

转载于:https://www.cnblogs.com/luxury/archive/2013/04/04/2999896.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376753.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ORACLE基本SQL语句-查询篇

一、普通查询 /*查询表数据*/select * from STU /*取出前3行数据*/select * from stu where ROWNUM<3 /*模糊查询*/select * from stu where stu_id like stu001% 说明&#xff1a;通配符“%”代表一个或者多个字符&#xff0c;通配符“_”代表一个字符。 /*别名*/select S…

三次握手建立失败的几种情况以及三次握手的理解

上面的图是阻塞式socket进行通信的过程&#xff0c;阻塞的时候是操作系统内核网络协议栈在工作 调用 connect 函数将激发 TCP 的三次握手过程&#xff0c;而且仅在连接建立成功或出错时才返回。其中出错返回可能有以下几种情况&#xff1a; 1、三次握手无法建立&#xff0c;客…

db_name,instance_name,service_names,db_domain,dbid,oracle_sid等区别与联系

最近整理了一篇文章&#xff1a;oracle listener 有网友对数据库是否显式设置了instance_name和service_names提出疑问。 由此引发出db_name,instance_name,oracle_sid等等这些常见的参数都代表什么意思&#xff0c;怎么取值的&#xff0c;有什么区别&#xff1f; SQL> sele…

检测版本更新

如果我们要检测app版本的更新&#xff0c;那么我们必须获取当前运行app版本的版本信息和appstore 上发布的最新版本的信息。 当前运行版本信息可以通过info.plist文件中的bundle version中获取&#xff1a; [cpp] view plaincopy NSDictionary *infoDic [[NSBundle mainBundle…

linux 启动/关闭多个py脚本

后台运行脚本 需求&#xff1a;很多时候我们会在 linux 服务器上执行 python 脚本&#xff0c;然而脚本程序执行的时间可能比较长&#xff0c;当耗时过长的情况下&#xff0c;我们使用 ssh 远程登录到 linux 服务器上容易造成超时自动断开连接&#xff0c;当用户注销时&#x…

在熟练使用2B铅笔前,请不要打开Axure

在互联网产品领域&#xff0c;Axure已成为产品经理、产品设计师以及交互设计师的必备工具&#xff0c;从某种程度讲&#xff0c;Axure帮助我们建立低保真模型&#xff0c;便于与用户的需求验证&#xff0c;也帮助我们构思交互细节&#xff0c;使前端和开发人员更容易理解我们的…

启用isqlplus

iSQL*Plus是sqlplus基于web方式发布的&#xff0c;要使用它只要在服务器上开启即可&#xff1a; [oraclelocalhost ~]$ isqlplusctl start perl: warning: Setting locale failed. perl: warning: Please check that your locale settings: LANGUAGE (unset), LC_ALL (unset)…

YUI 的模块信息配置优先级关系梳理

背景 YUI的配置参数较多&#xff0c; 可以在好几个地方配置一个module的相关信息&#xff0c; 如&#xff1a; //在全局配置&#xff0c; 所以YUI实例共享 YUI_config {modules: {w-autcomplete: {requires: [module1],path: test1.js,}},groups: {modules: {w-autocomplete: …

echarts 怎么知道鼠标点击的哪根柱子

有个需求&#xff0c;点击柱子&#xff0c;然后得到该柱子的信息&#xff0c;然后展示这个机房的时序图。 第一步卡住了&#xff0c;就是不知道如何获取柱子的序号。后参考&#xff1a;https://blog.csdn.net/zt_fucker/article/details/72461572?utm_sourceblogxgwz1 得到思路…

Oracle经典sql语句总结@sql-plus重点函数串讲与sql语句案例@中文排序详讲).doc

1.经典的select sql语句 //注意&#xff1a;包含空值的数学表达式求出的结果为空值 SQL> select salcomm from emp; //连接员工编号与员工姓名这两个字段 SQL> select empno||ename as "员工编号和员工姓名" from emp; //查询去掉重复行的员工部门编号 SQL>…

C++模板简单分析与举例

C模板简单分析与举例 #pragma once #include <iostream> /*/ C 模板 /*/ /* --- 函数模板 --- */ /// 声明 template <typename T1, typename T2> void TFunc(T1, T2); /// 一般定义 template <typename T1, typename T2> void TFunc(T1, T2) { std::cout &l…

flash builder4.7 for Mac升级AIRSDK详解

使用flash builder 打包ANE时或者打包ipa时候常常会遇到AIRSDK版本低的问题&#xff0c;然而flash builder4.7默认使用的AIRSDK是3.4而flash builder4.7 中 Flex SDK中默认的AIRSDK是3.1,大家可能有疑问怎么有二个AIRSDK。我的理解是Flex SDK中的AIRSDK是低版本&#xff0c;低版…

echarts formatter鼠标悬停显示信息

由于echarts中柱状图&#xff0c;鼠标放上去默认显示的是x轴名称以及y轴值。 而我现在需要再添加一些显示信息。 下面是操作&#xff1a; 在tooltip对象中补充trigger: “axis”,属性&#xff0c;然后再设置formatter。 tooltip : {formatter: function (params) {// do some …

codeforces 261 D

题目链接&#xff1a; 解题报告&#xff1a;给出一个序列a1,a2,a3.........an&#xff0c;f(i , j ,x) ak 等于x的个数(i < k < j)&#xff0c;令i < j&#xff0c;求有多少对 i 和 j 使得 f(1,i,ai) > f(j,n,aj)。 从左往右扫一遍这个序列&#xff0c;num1[i] 等于…

javascript下漢字和Unicode編碼互轉代碼

近日在為網站做一資料功能&#xff0c;這些顯示在頁面上面的文字數據都是存放在js文件裏面的&#xff0c;由於這些js文件裏面的中文都是經過unicode編碼的&#xff0c;頁面上顯示是沒有問題的&#xff0c;問題是我做的網站是繁體中文&#xff0c;而js文件裏面的中文數據是簡體中…

python 线程异步执行踩坑

有个需求&#xff0c;一个线程在得到n个数据之后&#xff0c;异步地执行一个子线程函数&#xff0c;在子线程函数中完成数据库的打开、写入数据、关闭操作。在子线程函数返回前父线程先返回结果。 在此之前&#xff0c;先导入我们需要的模块&#xff1a; from concurrent.futu…

关于window.history.back()后退问题

Windows下的window.history.back()后退后返回的不仅仅是前一个页而是前一个页的状态。假设一个页我改动了3次那必须后退3次才干回到前一个页。并且数据库中删除的数据依旧显示在上面感觉很的不有用。 解决的方法&#xff1a;history.back()后再加一个reload()这样就能够回到刷新…

每日英语:Smog Levels in Hong Kong Hit Highs

Hong Kong’s pollution levels hit nearly decade-level highs this week, sending locals scurrying inside and obscuring the city’s skyline behind a blanket of white. scurry&#xff1a;急跑&#xff0c;急赶    In the city’s central business district, road…

转载 | pymysql.err.InterfaceError: (0, ‘‘)解决办法

导致这个错误的原因是通过pymysql连接MySQL&#xff0c;没有关闭连接的操作&#xff0c;所以短时间内不会出问题&#xff0c;长时间保持这个连接会出现连接混乱。虽然看着自己的代码没错&#xff0c;还是会报 pymysql.err.InterfaceError: (0, ‘’)错误。所以这个连接要么连上…

不使用物理引擎,自己动手做真实物理的模拟投篮游戏

最近打算做一个2D投篮游戏&#xff0c;由于对于BOX2D等物理引擎并不熟悉&#xff0c;加之一开始低估了游戏所需要的碰撞检测复杂度&#xff0c;认为仅仅涉及4面墙&#xff0c;篮球&#xff0c;篮板&#xff0c;篮筐&#xff0c;篮网的碰撞检测并不复杂。因此决定自己实现所需要…