原文链接

PGI的官方网站上获得示例代码:

http://www.pgroup.com/lit/samples/pgi_accelerator_examples.tar

我们的第一个例子从一个简单的程序开始。这个程序是把一个浮点向量送到GPU上,然后乘以2.再把结果返回。
整个程序是:

 #include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main( int argc, char* argv[] )
{
int n; /* size of the vector */
float *a; /* the vector */
float *restrict r; /* the results */
float *e; /* expected results */
int i;
if( argc > )
n = atoi( argv[] );
else
n = ;
if( n <= ) n = ;
a = (float*)malloc(n*sizeof(float));
r = (float*)malloc(n*sizeof(float));
e = (float*)malloc(n*sizeof(float));
/* initialize */
for( i = ; i < n; ++i ) a[i] = (float)(i+);
#pragma acc kernels loop
for( i = ; i < n; ++i ) r[i] = a[i]*2.0f;
/* compute on the host to compare */
for( i = ; i < n; ++i ) e[i] = a[i]*2.0f;
/* check the results */
for( i = ; i < n; ++i )
assert( r[i] == e[i] );
printf( “%d iterations completed\n”, n );
return ;
}

请注意,在对指针r的声明中使用了 restrict 关键字; 我们很快就会知道为什么。
还请注意,定义浮点常量2.0f 而不是2.0 。在默认情况下,C语言的浮点常量是双精度。表达式a*2将会作为双精度计算,就好像(float)((double)a * 2.0)。为了避免这样,定义浮点常量,或者使用编译器选项-Mfcon,这样告诉编译器将浮点指针常量默认为通常的浮点来处理。
我们把进入GPU的循环之前放了一个kernals loop指令。这是告诉编译器去在查找循环的并行性,将数据传输到GPU上,在GPU上进行计算,然后将数据返回。对于这个程序,很简单。只需要输入下面的命令:

% pgcc -o c1.exe c1.c -acc -Minfo

也可以输入如下命令:

请注意-acc和-Minfo指令。-acc可以在编译器里启动OpenACC指令,默认情况下,PGI编译器认为目标加速区域在一个NVIDIA GPU上。我们会在后面的例子里演示其他的选项。
-Minfo指令就是从编译器上获得信息。我们将在我们的例子里解释这些信息代表的意思。当你在调试性能的时候,你会非常想了解这些信息的意思。
如果一切都安装正确,你就会从pgcc上获得以下信息:

 main:
, Generating copyout(r[:n])
Generating copyin(a[:n])
Generating compute capability 1.0 binary
Generating compute capability 2.0 binary
, Loop is parallelizable
Accelerator kernel generated
, #pragma acc loop gang, vector(128)
/* blockIdx.x threadIdx.x */

让我解释几个信息,首先是:
Generating copyout(r[:n]) 
就是告诉你在GPU上分配了数组r, 在循环执行后,把数据从GPU上复制回主机上。 
Generating copyin(a[:n]) 
就是告诉你编译器认为数组a 为循环的输入,因此数组a的n个元素需要从CPU上复制到GPU上。
Loop is paralleizable
就是告诉你编译器分析循环体的参数后认为所有的迭代可以并行执行。我们增加了restrict关键词在指针r的声明,否则编译器不能确保a和r指向不同的mermory
Accelerator kernal generated
这是告诉你,编译器已经成功地把循环体转化成GPU的一个内核。这个内核是GPU自己的函数,由编译器产生,将会被程序调用,并在GPU上并行执行。
这样,你准备运行程序。假设你是在GPU设备上执行,只需要输入执行文件的名字,acc_c1.exe.如果你得到一个信息 
libcuda.so not found, exiting
那么你可能是没有在它默认的位置安装CUDA驱动。你可能不得不设置环境变量LD_LIBRARY_PATH.
程序运行结束,你应该会看到一个结果:
100000 iterations completed
你如何知道哪些在GPU上执行?你可以设置环境变量ACC_NOTIFY为1.
csh: setenv ACC_NOTIFY 1
bash: export ACC_NOTIFY=1
然后重新运行程序。它会指出每次一个GPU内核执行的行数。在这个程序中,你会看到下面的结果:
launch kernel file=acc_c1.c function=main
line=25 device=0 grid=391 block=25
这是告诉你内核的文件名,函数,以及行数,CUDA grid和线程块的大小。
你可能不想给你所有的程序都设置这个环境变量,但在程序开发和测试的时候,这是个有用的办法。

最新文章

  1. [Android]使用MVP解决技术债务(翻译)
  2. 从Sql Server表中随机获取一些记录最简单的方法
  3. hdoj 1002 A+B(2)
  4. Linux 学习笔记 文件权限
  5. UVa 1471 (LIS变形) Defense Lines
  6. 基于visual Studio2013解决C语言竞赛题之0602最大值函数
  7. List Set Map用法和区别
  8. MySQL之自定义函数
  9. “this kernel requires an x86-64 CPU, but only detects an i686 CPU, unable to boot” 问题解决
  10. KD树
  11. 数据库事务的4个特性ACID
  12. SpringBoot操作数据库 2017.12.14
  13. 亿级流量场景下,大型架构设计实现【全文检索高级搜索---ElasticSearch篇】-- 中
  14. Py西游攻关之Socket网络编程
  15. 十三、事务、连接池 、ThreadLocal 、BaseServlet自定义Servlet父类 、 DBUtils &#224; commons-dbutils
  16. CentOS7(64)环境使用rpm命令安装gcc
  17. C语言程序设计II—第四周教学
  18. php中如何解决显示数据库中的内容乱码
  19. PAT甲题题解-1109. Group Photo (25)-(模拟拍照排队)
  20. JMS(Java消息服务)

热门文章

  1. jq二级目录
  2. Unity GameObject.FindObjectOfType&lt;&gt;(); 按类型查找游戏对象
  3. 理解 Linux backlog/somaxconn 内核参数
  4. (转) HTTP &amp; HTTPS网络协议重点总结(基于SSL/TLS的握手、TCP/IP协议基础、加密学)
  5. Quartz使用(3) - Quartz核心接口Trigger
  6. 移动Web开发与适配笔记
  7. ORACLE 查看表空间
  8. StreamWrite类
  9. c# 使用泛型序列化
  10. jq中事件绑定的方法