▶ 使用 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. php MySQL()函数

    1.mysql_query() 函数执行一条 MySQL 查询:mysql_query(query,connection) 2.mysql_fetch_array() 函数 3.mysql_fetch ...

  2. python3反射

    class Cmd:# def __init__(self,name):# self.name = name def run(self): while 1: cmd = input('>> ...

  3. 《DSP using MATLAB》Problem 4.24

    Y(z)部分分式展开, 零状态响应部分分式展开, 零输入状态部分分式展开,

  4. python 直接将list 整体转化-----------map()

    假设有这样一个 results = ['1', '2', '3'] 转化为下面这个样子 results = [1, 2, 3] 我们可以使用map函数 在Python2中这样操作: results = ...

  5. 使用ioctl获取网卡统计信息

    ethtool -S获取接口统计信息总共分三步: 1.获取统计项个数,使用SIOCETHTOOL+ETHTOOL_GSSET_INFO 2.(可选)获取统计项名字,使用SIOCETHTOOL+ETHT ...

  6. 前端基础之HTML快速入门

    什么是 HTML? HTML 是用来描述网页的一种语言. HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (ma ...

  7. java 方向术语

    缩写 英文 中文意思 POJO Plain Ordinary Java Object 简单的Java对象 slf4j Simple Logging Facade for Java 简单日志门面,跟 C ...

  8. FineUI中在一个页面中通过控件事件(JS)向父页面中添加Tab页

    1.在前台页面尾部添加js代码 </form>    <script type="text/javascript">        var basePath ...

  9. 添加pptp、l2tp客户端

    一.编译 -> Network -> Network ->VPN 二.配置 1. L2TP配置 network配置文件增加: config interface 'vpn1' opti ...

  10. ComboBox智能搜索功能

    cmbList.AutoCompleteSource = AutoCompleteSource.ListItems; cmbList.AutoCompleteMode = AutoCompleteMo ...