OpenACC kernels
▶ 使用 kernels 导语并行化 for 循环
● 一重循环
#include <stdio.h>
#include <time.h>
#include <openacc.h> const int row = * * ; int main()
{
int a[row], b[row], c[row];
for (int i = ; i < row; ++i) // 填充 a 和 b
a[i] = b[i] = i; clock_t time = clock();
#ifdef _OPENACC // 使用 OpenACC 时执行本段
#pragma acc kernels
for (int i = ; i < row; ++i) // c = a + b
c[i] = a[i] + b[i];
time = clock() - time;
printf("\nTime with acc:%d ms\n", time);
#else // 不用 OpenACC 时执行本段
for (int i = ; i < row; i++)
c[i] = a[i] + b[i];
time = clock() - time;
printf("\nTime without acc:%d ms\n", time);
#endif
getchar();
return ;
}
● 输出结果
D:\Code\OpenACC>pgcc main.c -o main-no-acc.exe -Minfo // 编译,-Minfo 要求输出编译优化信息,没有额外输出 D:\Code\OpenACC>pgcc main.c -o main.exe -Minfo -acc // 编译,-acc 要求使用 OpenACC
main:
, Generating implicit copyin(b[:row]) // 数据管理控制
Generating implicit copyout(c[:row])
Generating implicit copyin(a[:row])
, Loop is parallelizable // 并行优化
Generating Tesla code
, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */ // 使用默认 vector 尺寸,注释是自动生成的 D:\Code\OpenACC>main-no-acc.exe Time without acc: ms D:\Code\OpenACC>main-acc.exe
launch CUDA kernel file=D:\Code\OpenACC\main.c function=main line= device= threadid= num_gangs= num_workers= vector_length= grid= block=
// 对代码第 16 行的 for 进行了并行优化,
Time with acc: ms // 使用第 0 号设备(GPU)
// 线程编号 1,使用 gang 65536 个,worker 1 个,vector 宽度 128
// CUDA 配置为 gridDim.x = 65536,blockDim.x = 128Time
// 每单元计算负载 = row / grid / block = 2
● 二重循环
#include <stdio.h>
#include <time.h>
#include <openacc.h> const int row = * , col = ; int main()
{
int a[row][col], b[row][col], c[row][col];
for (int i = ; i < row; i++) // 填充 a 和 b
{
for (int j = ; j < col; j++)
a[i][j] = b[i][j] = i * j;
} clock_t time = clock();
#ifdef _OPENACC
#pragma acc kernels
for (int i = ; i < row; i++) // c = a + b
{
for (int j = ; j < col; j++)
c[i][j] = a[i][j] + b[i][j];
}
time = clock() - time;
printf("\nTime with acc:%d ms\n", time);
#else
for (int i = ; i < row; i++)
{
for (int j = ; j < col; j++)
c[i][j] = a[i][j] + b[i][j];
}
time = clock() - time;
printf("\nTime without acc:%d ms\n", time);
#endif
getchar();
return ;
}
● 输出结果
D:\Code\OpenACC>pgcc main.c -o main-no-acc.exe -Minfo D:\Code\OpenACC>pgcc main.c -o main-acc.exe -Minfo -acc
main:
, Generating implicit copyin(a[:row][:col])
Generating implicit copyout(c[:row][:col])
Generating implicit copyin(b[:row][:col])
, Loop is parallelizable
, Loop is parallelizable
Generating Tesla code
, #pragma acc loop gang, vector(4) /* blockIdx.y threadIdx.y */ // 高一层的循环使用的是 worker
, #pragma acc loop gang, vector(32) /* blockIdx.x threadIdx.x */ D:\Code\OpenACC>main-no-acc.exe Time without acc: ms D:\Code\OpenACC>main-acc.exe
launch CUDA kernel file=D:\Code\OpenACC\main.c function=main line= device= threadid= num_gangs= num_workers= vector_length= grid=16x2048 block=32x4
// 注意参数变化,仍有 num_gangs = grid,num_workers * vector_length = block
Time with acc: ms // 每单元计算负载 = row * col / grid / block = 4
● 三重循环
#include <stdio.h>
#include <time.h>
#include <openacc.h> const int row = , col = , page = ; int main()
{
int a[row][col][page], b[row][col][page], c[row][col][page];
for (int i = ; i < row; i++) // 填充 a 和 b
{
for (int j = ; j < col; j++)
{
for (int k = ; k < page; k++)
a[i][j][k] = b[i][j][k] = i * j + k;
}
}
clock_t time = clock();
#ifdef _OPENACC
#pragma acc kernels
for (int i = ; i < row; i++) // c = a + b
{
for (int j = ; j < col; j++)
{
for (int k = ; k < page; k++)
c[i][j][k] = a[i][j][k] + b[i][j][k];
}
}
time = clock() - time;
printf("\nTime with acc:%d ms\n", time);
#else
for (int i = ; i < row; i++)
{
for (int j = ; j < col; j++)
{
for (int k = ; k < page; k++)
c[i][j][k] = a[i][j][k] + b[i][j][k];
}
}
time = clock() - time;
printf("\nTime without acc:%d ms\n", time);
#endif
getchar();
return ;
}
● 输出结果
D:\Code\OpenACC>pgcc main.c -o main-no-acc.exe -Minfo D:\Code\OpenACC>pgcc main.c -o main-acc.exe -Minfo -acc
main:
, Generating implicit copyin(b[:row][:col][:page])
Generating implicit copyout(c[:row][:col][:page])
Generating implicit copyin(a[:row][:col][:page])
, Loop is parallelizable
, Loop is parallelizable
, Loop is parallelizable
Generating Tesla code
, #pragma acc loop gang /* blockIdx.y */ // 最高层循环尝试调整 grid
, #pragma acc loop gang, vector(4) /* blockIdx.z threadIdx.y */
, #pragma acc loop gang, vector(32) /* blockIdx.x threadIdx.x */ D:\Code\OpenACC>main-no-acc.exe Time without acc: ms D:\Code\OpenACC>main-acc.exe
launch CUDA kernel file=D:\Code\OpenACC\main.c function=main line= device= threadid= num_gangs= num_workers= vector_length= grid=16x128x16 block=32x4
// grid 变成了三维
Time with acc: ms // 每单元计算负载 = row *col * page / grid / block = 4
// row 改为 64,则 grid=16x128x16 block=32x4,计算负载 = 2
// col 改为 128,则 grid=16x128x16 block=32x4,计算负载 = 2
// page 改为 256,则 grid=8x128x32 block=32x4,计算负载 = 2
// row 改为 32,则 grid=16x32x64 block=32x4,计算负载 = 1
● 在 ubuntu 上跑一重循环的代码,注意计时器单位是 μs
cuan@CUAN:~/Temp$ pgcc -acc main.c -o main.exe
cuan@CUAN:~/Temp$ pgcc main.c -o main-no-acc.exe
cuan@CUAN:~/Temp$ ./main.exe Time with acc: us cuan@CUAN:~/Temp$ ./main-no-acc.exe Time without acc: us
OpenACC kernels的更多相关文章
- 7.OpenACC
OpenACC: openacc 可以用于fortran, c 和 c++程序,可以运行在CPU或者GPU设备. openacc的代码就是在原有的C语言基础上进行修改,通过添加:compiler di ...
- OpenACC 梯度下降法求解线性方程的优化
▶ 书上第二章,用一系列步骤优化梯度下降法解线性方程组.才发现 PGI community 编译器不支持 Windows 下的 C++ 编译(有 pgCC 命令但是不支持 .cpp 文件,要专业版才支 ...
- OpenACC 优化矩阵乘法
▶ 按书上的步骤使用不同的导语优化矩阵乘法 ● 所有的代码 #include <iostream> #include <cstdlib> #include <chrono ...
- OpenACC 与 CUDA 的相互调用
▶ 按照书上的代码完成了 OpenACC 与CUDA 的相互调用,以及 OpenACC 调用 cuBLAS.便于过程遇到了很多问题,注入 CUDA 版本,代码版本,计算能力指定等,先放在这里,以后填坑 ...
- OpenACC Julia 图形
▶ 书上的代码,逐步优化绘制 Julia 图形的代码 ● 无并行优化(手动优化了变量等) #include <stdio.h> #include <stdlib.h> #inc ...
- OpenACC 异步计算
▶ 按照书上的例子,使用 async 导语实现主机与设备端的异步计算 ● 代码,非异步的代码只要将其中的 async 以及第 29 行删除即可 #include <stdio.h> #in ...
- OpenACC 书上的范例代码(Jacobi 迭代),part 3
▶ 使用Jacobi 迭代求泊松方程的数值解 ● 使用 data 构件,强行要求 u0 仅拷入和拷出 GPU 各一次,u1 仅拷入GPU 一次 #include <stdio.h> #in ...
- OpenACC数据管理语句
▶ 书中第4章,数据管理部分的代码和说明 ● 代码,关于 copy,copyin,copyout,create #include <stdio.h> #include <openac ...
- OpenACC 书上的范例代码(Jacobi 迭代),part 2
▶ 使用Jacobi 迭代求泊松方程的数值解 ● 首次使用 OpenACC 进行加速,使用动态数组,去掉了误差控制 #include <stdio.h> #include <stdl ...
随机推荐
- 响应式有利于SEO还是pc+手机端分开url有利于SEO?
一早上都在查这个问题,大家都来讨论一下. 首先,可以肯定的是,如果公司推广重在谷歌,要做响应式.但是对于百度推广呢??虽然响应式是趋势,但是目前而言,对于百度怎样好呢
- 初学者必读之AJAX简单实例2
1.a前台页面的主体 b.添加script函数: 这个函数功能1:把文本框的数据传入到后台程序 2.再接收后台程序处理之后的数据,将其插入到页面 2.后台程序功能 软件测试
- redash docker 运行
redash .superset .metabase 都是很不错的数据分析工具,支持多种数据源,同时可以方便的生成报表 基本上都支持定制化报表界面.通知(定时),metabase 有点偏产品,supe ...
- Javascript undefined 和 null
Javascript undefined 和 null 虽然 Javascript 一切皆对象,但是类型还是有区别的. undefined 表示 未定义的数据类型. null 表示空对象. 在判断时没 ...
- 【转】每天一个linux命令(58):telnet命令
原文网址:http://www.cnblogs.com/peida/archive/2013/03/13/2956992.html telnet命令通常用来远程登录.telnet程序是基于TELNET ...
- Angular 4 组件间的通信
一.输入属性(父组件与子组件通信) 1. 创建工程 ng new demo1 2.创建order组件 ng g component order 3. 在order组件里定义输入属性 order组件的h ...
- C# 爬取网页上的数据
最近工作中需求定时爬取不同城市每天的温度.其实就是通过编程的方法去抓取不同网站网页进行分析筛选的过程..NET提供了很多类去访问并获得远程网页的数据,比如WebClient类和HttpWebReque ...
- debian之apt源
美国的 deb http://ftp.us.debian.org/debian stable main contrib non-freedeb-src http://ftp.us.debian.org ...
- BASIC-5_蓝桥杯_查找整数
示例代码: #include <stdio.h>#include <stdlib.h> int main(void){ int n = 0 , key = 0 , count ...
- bzoj 1414: [ZJOI2009]对称的正方形
Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...