编写第一个OpenACC程序
在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和线程块的大小。
你可能不想给你所有的程序都设置这个环境变量,但在程序开发和测试的时候,这是个有用的办法。
编写第一个OpenACC程序的更多相关文章
- 搭建java开发环境、使用eclipse编写第一个java程序
搭建java开发环境.使用eclipse编写第一个java程序 一.Java 开发环境的搭建 1.首先安装java SDK(简称JDK). 点击可执行文件 jdk-6u24-windows-i586. ...
- 【安装eclipse, 配置java环境教程】 编写第一个java程序
写java通常用eclipse编写,还有一款编辑器比较流行叫IJ.这里我们只说下eclipse编写java的前期工作. 在安装eclipse之前要下载java的sdk文件,即java SE:否则无法运 ...
- 【C#入门教案-02】用记事本编写第一个C#程序-Hello World
02-用记事本编写第一个C#程序-Hello World 广东职业技术学院 欧浩源 [1]进行.NET程序开发的最基本环境配备 .NET Framework + 代码编辑工具(记事本或Noetpad ...
- 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)
上一篇我们学习了MapReduce的原理,今天我们使用代码来加深对MapReduce原理的理解. wordcount是Hadoop入门的经典例子,我们也不能免俗,也使用这个例子作为学习Hadoop的第 ...
- 从零自学Java-1.编写第一个Java程序
编写第一个Java程序 完成工作:1.在文本编辑器中输入一个Java程序. 2.使用括号组织程序. 3.保存.编译和运行程序. package com.Jsample;//将程序的包名称命名为com. ...
- Java笔记:编写第一个Java程序
2017.6.17 1.编写第一个Java程序 创建text文本,命名第一个Java程序.txt 在里面编写Java代码 public class Demo1{ public static void ...
- 假期作业02:安装JDK与文本编辑器并编写第一个Java程序
假期作业02:安装JDK与文本编辑器并编写第一个Java程序 一.安装JDK与文本编辑器并编写第一个java程序 首先在oracle官网(需要创建账号,进行登录后方可使用)按照自己的需求下载JDK(h ...
- 编写第一个MapReduce程序—— 统计气温
摘要:hadoop安装完成后,像学习其他语言一样,要开始写一个“hello world!” ,看了一些学习资料,模仿写了个程序.对于一个C#程序员来说,写个java程序,并调用hadoop的包,并跑在 ...
- 使用Playground编写第一个Swift程序
从控制台输出“HelloWorld”是我学习C语言的第一步,也是我人生中非常重要的一步.多年后的今天,我仍希望以HelloWorld作为第一步,与大家共同开启一个神奇.瑰丽的世界——Swift编程. ...
随机推荐
- Android中的下拉列表
在Web开发中,HTML提供了下拉列表的实现,就是使用<select>元素实现一个下拉列表,在其中每个下拉列表项使用<option>表示即可.这是在Web开发中一个必不可少的交 ...
- jndi理解
java中很多这些接口规范,jndi就是其中一个,而下面那些包就是jndi接口的提供商程序实现包,他们都是遵循jndi规范的. 主要接口功能是:添加命名与对象的映射到jndi树中,客户能快速查找并使用 ...
- [转] javascript另类方法高效实现htmlencode()与htmldecode()函数
本文转自:http://blog.csdn.net/cuixiping/article/details/7846806 最常见的做法是采用正则表达式替换的方法,将特殊字符如 < > &am ...
- 牛客网Java刷题知识点之字符流缓冲区、BufferedWriter、BufferedReader、BufferedReader-readLine方法原理、自定义MyBufferedReader-read方法、自定义MyBufferedReader-readLine方法
不多说,直接上干货! 把提高效率的动作,封装成一个对象.即把缓冲区封装成一个对象. 就是在一个类里封装一个数组,能对流锁操作数据进行缓存. 什么是字符流缓冲区? 善于使用字符流缓冲区,减轻负担,提高下 ...
- 安装weblogic步骤
1 mkdir -p /home/geekc3t/weblogic 创建weblogic安装目录2 groupadd weblogic 创建weblogic组3 useradd -g weblogic ...
- ZK使用
1. 关注问题 1. zookeeper集群如何保证请求的均匀分布? 由client建立连接时会随机取server保证均匀分布, 2.已布置完成的ZK集群如何扩容? 修改配置后逐台重启即可 2. ZK ...
- 【PHP】 hash加密
之前对密码进行加密是在JS文件里做的,但是不行,改到PHP文件里进行加密比较安全,于是乎…… [原JS加密代码] var password = sha256_digest(pwd); 后来在网上调查方 ...
- 详细记录vue项目实战步骤(含vue-cli脚手架)
一.通过vue-cli创建了一个demo. (vue-cli是快速构建这个单页应用的脚手架,本身继承了多种项目模板:webpack(含eslit,unit)和webpack-simple(无eslin ...
- jQuery UI dialog 隐藏默认关闭按钮
var O_dialog = $("#dialog-modal"); O_dialog.dialog({ closeOnEscape: false, width: 250, hei ...
- C# 十进制与二进制、十六进制、八进制之间的转换
1.十进制 转 二进制 将十进制数不断地除2,将所有余数倒叙填写,即可得到所需二进制数据. public static string DecimalToBinary(int vDecimal) { / ...