▶ 使用 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的更多相关文章

  1. 7.OpenACC

    OpenACC: openacc 可以用于fortran, c 和 c++程序,可以运行在CPU或者GPU设备. openacc的代码就是在原有的C语言基础上进行修改,通过添加:compiler di ...

  2. OpenACC 梯度下降法求解线性方程的优化

    ▶ 书上第二章,用一系列步骤优化梯度下降法解线性方程组.才发现 PGI community 编译器不支持 Windows 下的 C++ 编译(有 pgCC 命令但是不支持 .cpp 文件,要专业版才支 ...

  3. OpenACC 优化矩阵乘法

    ▶ 按书上的步骤使用不同的导语优化矩阵乘法 ● 所有的代码 #include <iostream> #include <cstdlib> #include <chrono ...

  4. OpenACC 与 CUDA 的相互调用

    ▶ 按照书上的代码完成了 OpenACC 与CUDA 的相互调用,以及 OpenACC 调用 cuBLAS.便于过程遇到了很多问题,注入 CUDA 版本,代码版本,计算能力指定等,先放在这里,以后填坑 ...

  5. OpenACC Julia 图形

    ▶ 书上的代码,逐步优化绘制 Julia 图形的代码 ● 无并行优化(手动优化了变量等) #include <stdio.h> #include <stdlib.h> #inc ...

  6. OpenACC 异步计算

    ▶ 按照书上的例子,使用 async 导语实现主机与设备端的异步计算 ● 代码,非异步的代码只要将其中的 async 以及第 29 行删除即可 #include <stdio.h> #in ...

  7. OpenACC 书上的范例代码(Jacobi 迭代),part 3

    ▶ 使用Jacobi 迭代求泊松方程的数值解 ● 使用 data 构件,强行要求 u0 仅拷入和拷出 GPU 各一次,u1 仅拷入GPU 一次 #include <stdio.h> #in ...

  8. OpenACC数据管理语句

    ▶ 书中第4章,数据管理部分的代码和说明 ● 代码,关于 copy,copyin,copyout,create #include <stdio.h> #include <openac ...

  9. OpenACC 书上的范例代码(Jacobi 迭代),part 2

    ▶ 使用Jacobi 迭代求泊松方程的数值解 ● 首次使用 OpenACC 进行加速,使用动态数组,去掉了误差控制 #include <stdio.h> #include <stdl ...

随机推荐

  1. hdu2072 单词数 字典树

    字典树裸题 #include<stdio.h> #include<string.h> ][]; ]; int cnt; int ans; void Insert(char *w ...

  2. chrom 自带截屏用法

    1 . F12调出控制台 2 . Ctrl+Shift+p 3 . 输入capture

  3. mysql安装错误解决办法

    在我们装mysql数据库时,出现安装失败是一件非常令人烦恼的事情,接下来小编就给大家带来在我们安装mysql数据库失败的一些解决方法,感兴趣的小伙伴们可以参考一下   mysql数据库安装不了了!my ...

  4. BitKeeper 和 Git

    在 2002 年到 2005年, Linux 内核使用 BitKeeper 管理代码. BitKeeper 的 CEO 和 Linus 曾经是好友. 在 Git 诞生 11年后 BitKeeper 宣 ...

  5. Apache Derby数据库 安装、知识点

    Apache Derby数据库 安装: 下载路径:http://archive.apache.org/dist/db/derby/ 出处:http://www.yiibai.com/hive/hive ...

  6. Ionic 中MD5加密使用

    1. 下载安装ts-md5 在项目的命令行工具里输入 npm  install ts-md5 --save 2. 使用 导入 import {Md5} from "ts-md5/dist/m ...

  7. c# ProgressBar进度条方向和美观

    protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.Style | ...

  8. Microsoft Dynamics CRM 4.0 如何添加自定义按钮

    一.通过导入导出ISV.Config(ISV配置),具体如下图: 先设置—>打开导出自定义项—>选择ISV配置—>选择导出所选自定义项 点击确定 保存到桌面,解压,用VS打开cust ...

  9. 【jmeter】jmeter之-聚合点

    集合点:简单来理解一下,虽然我们的“性能测试”理解为“多用户并发测试”,但真正的并发是不存在的,为了更真实的实现并发这感念,我们可以在需要压力的地方设置集合点, 还拿那个用户和密码的地方,每到输入用户 ...

  10. OpenFileDialog 打开快捷方式时,返回的是快捷方式引用的路径,而不是快捷方式(.lnk)自身的路径

    OpenFileDialog 打开 .lnk 文件. OpenFileDialog 有个DereferenceLinks 属性:获取或设置一个值,该值指示文件对话框是返回快捷方式引用的文件的位置,还是 ...