基于指令的移植方式的几个重要概念的理解(OpenHMPP, OpenACC)-转载
2015-03-22 15:20
357 查看
引言:
什么是基于指令的移植方式呢?首先我这里说的移植可以理解为把原先在CPU上跑的程序放到像GPU一样的协处理器上跑的这个过程。在英文里可以叫Porting。移植有两种方式:一种是使用CUDA或者OpenCL来重新设计代码,然后使用硬件厂商提供的编译器来编译;一种是使用OpenACC或者OpenHMPP提供的指令集添加到你想使用GPU计算的源代码中的某个位置,让编译器来编译出GPU上执行的代码。后一种方式就是基于指令的移植方式。
例如,下面一个简单的循环:
如果你想把这个循环放到GPU上,让每个线程计算一次i的话,可以这样做:
#pragma acc kernels
网格化(gridification)
这样,编译器拿到加了OpenACC指令的那段代码后,就会把你的循环放到GPU或者其他硬件加速器(例如MIC)上。编译器分析了#pragma acc kernels下面的那个循环,就会根据循环的次数来分配线程数量,这个过程就叫网格化。为什么说是网格化呢?可以这样理解,因为GPU可以启动很多线程,这些线程就像一张渔网一样,可以认为一个网格代表一个线程,所以我就干脆叫这个过程为“网格化”了。
内核(kernel)
在OpenACC里可以这样理解内核:内核就是在协处理器(例如GPU)上被多个线程同时执行的一段代码。如果每个线程都做一个活,岂不是没意思了么?当然不是这样的,他们执行的代码是一样的,但是每个线程可以根据自己的ID号来针对不同的数据做同样的工作,这也就是数据并行的含义。
codelet
使用CAPS的HMPP Workbench编译加了OpenACC指导语句的源代码时,编译器会告诉你codelet产生了。实际上产生了一个CUDA或者OpenCL的源文件,这个源文件中包含了根据你的指导语句生成的CUDA或者OpenCL的源代码。那什么是codelet呢?可以认为codelet就是数据管理+内核。一个codelet要干的事情包括两部分:申请和管理CPU和协处理器之间的存储,还有就是启动在协处理上执行的代码。
work-sharing
这个词可以理解为名词“共享工作”。如果在协处理器上的线程们执行的工作时work-sharing的,那么每个线程可以根据自己的ID在不同的数据上干了相似的工作。这个词是在使用OpenACC或者OpenHMPP移植代码的时候遇到的,它描述的是CPU的串行代码中的状态,例如:
在这段代码中,a[i]的计算与a[i]之外的a的元素没有依赖性,所以,每次循环的i可以使独立的完成的,像这样的状态就是work-sharing的。还有例如规约:
虽然s的计算与i相关,但是细想一下,加法在数学上市满足交换律的,s的每次加a[i]实际上不相关的,你不管以什么顺序加和a[i]到s,解结果总是一样的。所以规约也可以理解为是worksharing 的。
什么是基于指令的移植方式呢?首先我这里说的移植可以理解为把原先在CPU上跑的程序放到像GPU一样的协处理器上跑的这个过程。在英文里可以叫Porting。移植有两种方式:一种是使用CUDA或者OpenCL来重新设计代码,然后使用硬件厂商提供的编译器来编译;一种是使用OpenACC或者OpenHMPP提供的指令集添加到你想使用GPU计算的源代码中的某个位置,让编译器来编译出GPU上执行的代码。后一种方式就是基于指令的移植方式。
例如,下面一个简单的循环:
for (i=0; i<n;i++) { dosomething(i); }
如果你想把这个循环放到GPU上,让每个线程计算一次i的话,可以这样做:
#pragma acc kernels
for (i=0; i<n;i++) { dosomething(i); }
网格化(gridification)
这样,编译器拿到加了OpenACC指令的那段代码后,就会把你的循环放到GPU或者其他硬件加速器(例如MIC)上。编译器分析了#pragma acc kernels下面的那个循环,就会根据循环的次数来分配线程数量,这个过程就叫网格化。为什么说是网格化呢?可以这样理解,因为GPU可以启动很多线程,这些线程就像一张渔网一样,可以认为一个网格代表一个线程,所以我就干脆叫这个过程为“网格化”了。
内核(kernel)
在OpenACC里可以这样理解内核:内核就是在协处理器(例如GPU)上被多个线程同时执行的一段代码。如果每个线程都做一个活,岂不是没意思了么?当然不是这样的,他们执行的代码是一样的,但是每个线程可以根据自己的ID号来针对不同的数据做同样的工作,这也就是数据并行的含义。
codelet
使用CAPS的HMPP Workbench编译加了OpenACC指导语句的源代码时,编译器会告诉你codelet产生了。实际上产生了一个CUDA或者OpenCL的源文件,这个源文件中包含了根据你的指导语句生成的CUDA或者OpenCL的源代码。那什么是codelet呢?可以认为codelet就是数据管理+内核。一个codelet要干的事情包括两部分:申请和管理CPU和协处理器之间的存储,还有就是启动在协处理上执行的代码。
work-sharing
这个词可以理解为名词“共享工作”。如果在协处理器上的线程们执行的工作时work-sharing的,那么每个线程可以根据自己的ID在不同的数据上干了相似的工作。这个词是在使用OpenACC或者OpenHMPP移植代码的时候遇到的,它描述的是CPU的串行代码中的状态,例如:
for (i=0; i<n; i++) { a[i] = i; }
在这段代码中,a[i]的计算与a[i]之外的a的元素没有依赖性,所以,每次循环的i可以使独立的完成的,像这样的状态就是work-sharing的。还有例如规约:
s = 0; for (i=0; i<n; i++) { s+=a[i]; }
虽然s的计算与i相关,但是细想一下,加法在数学上市满足交换律的,s的每次加a[i]实际上不相关的,你不管以什么顺序加和a[i]到s,解结果总是一样的。所以规约也可以理解为是worksharing 的。
相关文章推荐
- 基于指令的移植方式的几个重要概念的理解(OpenHMPP, OpenACC)
- 基于指令的移植方式的几个重要概念的理解(OpenHMPP, OpenACC)
- 基于指令的移植方式的几个重要概念的理解(OpenHMPP, OpenACC)
- (三)(1) Z-Stack协议中几个重要概念的理解
- object-c 要理解协议的几个重要概念
- 理解并发编程中的重要概念:指令重排序和指令乱序执行
- Z-Stack协议中几个重要概念的理解
- OpenStreetMap初探(三)——几个重要概念
- [转载]对于可重入、线程安全、异步信号安全几个概念的理解
- Java EE几个重要概念理解
- 【转载】Spark学习——spark中的几个概念的理解及参数配置
- 单点登录cas常见问题(十三) - 几个重要概念怎么理解?
- 【转载】全面理解javascript的caller,callee,call,apply概念(修改版)
- javascript中重要概念-闭包-深入理解
- 基于WDF的PCI/PCIe接口卡Windows驱动程序(2)-开发者需要了解的WDF中的一些重要的概念
- 面向对象的几个基本概念的理解
- (重要!)Spring AOP概念理解 (通俗易懂)
- SIP协议入门:初学者必须明白的几个重要概念
- IntelliJ IDEA 项目相关的几个重要概念介绍
- 我的IM - 基础篇[3] - 基于UDP通讯的IM设计[基于XML格式的网络通讯协议 以及 包解析器和包处理器的基础概念] 【转载】