▶ 使用 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. 20155204 2016-2017-2 《Java程序设计》第7周学习总结

    20155204 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 在只有Lambda表达式的情况下,参数的类型必须写出来,如果有目标类型的话,在编译程序可推断 ...

  2. 关于Hibernate性能优化之 FetchType=Lazy时查询数据

    当表A和表B一对多的关系 对于A和B的实体类,设置FetchType=EAGER时,取A表数据,对应B表的数据都会跟着一起加载,优点不用进行二次查询.缺点是严重影响数据查询的访问时间. 解决办法Fet ...

  3. test20181006 石头剪刀布

    题意 分析 考场做法同题解一样. std代码. #include<bits/stdc++.h> using namespace std; template <typename T&g ...

  4. pandas 基础用法

    pandas 是一个基于 Numpy 构建, 强大的数据分析工具包 主要功能 独特的数据结构 DataFrame, Series 集成时间序列功能 提供丰富的数学运算操作 灵活处理缺失数据 Serie ...

  5. ArrayList和LinkedList插入删除效率的测试(完全不在一个数量级8/20)

    通过index获取元素的值 java里面的链表可以添加索引,而C中的链表,是没有索引的 package ArrayListVSLinkedList; import java.util.ArrayLis ...

  6. ehci及其伴随ohci主机控制器驱动分析

    1. 正常插入 插上U盘产生中断调用usb_hcd_irq: usb_hcd_irq ehci_irq usb_hcd_resume_root_hub queue_work(pm_wq, &h ...

  7. 【转】linux下终端命令快捷键

    原文网址:http://daaoao.blog.51cto.com/2329117/554177 linux下使用终端不可避免. 使用终端快捷键,当然会使你如虎添翼.记住他们吧 终端快捷键 tab=补 ...

  8. 【转】每天一个linux命令(15):tail 命令

    原文网址:http://www.cnblogs.com/peida/archive/2012/11/07/2758084.html tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f ...

  9. mysql ssh 端口转发

    某些时候 mysql  只允许 指定的 ip连接 .这时候怎么在本机 连接mysql 的呢? 条件 1 mysql 只有 允许 指定ip连接 2 有连接 指定 ip 服务器的  账密 这时候我们可以通 ...

  10. bzoj 4929: 第三题

    Description 给定n,b,c,d,e以及A0,A1,···,An−1,定义 xk=b×c^4k+d×c^2k+e f(x)=Sigma(Aix^i),0<=i<=n-1 请你求出 ...