▶ CPU - GPU 异步操作

▶ 源代码

 #include <stdio.h>
#include <cuda_runtime.h>
#include "device_launch_parameters.h"
#include <helper_cuda.h>
#include <helper_functions.h> __global__ void increment_kernel(int *g_data, int inc_value)
{
int idx = blockIdx.x * blockDim.x + threadIdx.x;
g_data[idx] = g_data[idx] + inc_value;
} bool correct_output(int *data, const int n, const int x)
{
for (int i = ; i < n; i++)
{
if (data[i] != x)
{
printf("Error! data[%d] = %d, ref = %d\n", i, data[i], x);
return false;
}
}
return true;
} int main(int argc, char *argv[])
{
printf("Start.\n");
int devID = findCudaDevice(argc, (const char **)argv); // 通过命令行参数选择设备,可以为空
cudaDeviceProp deviceProps;
cudaGetDeviceProperties(&deviceProps, devID);
printf("CUDA device [%s]\n", deviceProps.name); const int n = * * ;
const int nbytes = n * sizeof(int);
const int value = ; int *a, *d_a;
cudaMallocHost((void **)&a, nbytes);
cudaMalloc((void **)&d_a, nbytes);
memset(a, , nbytes);
cudaMemset(d_a, , nbytes); cudaEvent_t start, stop; // GPU 端计时器
cudaEventCreate(&start);
cudaEventCreate(&stop); StopWatchInterface *timer = NULL; // CPU 端计时器
sdkCreateTimer(&timer);
sdkResetTimer(&timer); dim3 threads = dim3(, , );
dim3 blocks = dim3(n / threads.x, , ); sdkStartTimer(&timer); // 注意 GPU 计时器是夹在 CPU 计时器内的,但是 GPU 函数都是异步的
cudaEventRecord(start, );
cudaMemcpyAsync(d_a, a, nbytes, cudaMemcpyHostToDevice, );
increment_kernel << <blocks, threads, , >> > (d_a, value);
cudaMemcpyAsync(a, d_a, nbytes, cudaMemcpyDeviceToHost, );
cudaEventRecord(stop, );
sdkStopTimer(&timer); unsigned long int counter = ; // 记录 GPU 运行完成以前 CPU 运行了多少次 while 的循环
while (cudaEventQuery(stop) == cudaErrorNotReady)
counter++; float gpu_time = 0.0f; // 此时保证 GPU 运行完成,才能记录时间
cudaEventElapsedTime(&gpu_time, start, stop); printf("time spent by GPU: %.2f\n", gpu_time);
printf("time spent by CPU: %.2f\n", sdkGetTimerValue(&timer));
printf("CPU executed %lu iterations while waiting for GPU to finish\n", counter);
printf("\n\tFinish: %s.", correct_output(a, n, value) ? "Pass" : "Fail"); cudaEventDestroy(start);
cudaEventDestroy(stop);
cudaFreeHost(a);
cudaFree(d_a);
getchar();
return ;
}

● 输出结果:

GPU Device : "GeForce GTX 1070" with compute capability 6.1

CUDA device [GeForce GTX ]
time spent by GPU: 11.50
time spent by CPU: 0.05
CPU executed iterations while waiting for GPU to finish Finish!

▶ 新姿势:

● 调用主函数时的第0个参数作为程序名字符串,可以用于输出。

 int main(int argc, char *argv[])
...
printf("%s", argv[]);

● 在没有附加 flag 的情况下申请主机内存,注意使用cudaFreeHost释放

 int *a, nbytes = n * sizeof(int);
cudaMallocHost((void **)&a, nbytes);
...
cudaFreeHost(a);

● 记录 CPU 调用 CUDA 所用的时间

 StopWatchInterface *timer = NULL;
sdkCreateTimer(&timer);
sdkResetTimer(&timer);
sdkStartTimer(&timer); ...// 核函数调用 sdkStopTimer(&timer);
printf("%.2f ms", sdkGetTimerValue(&timer));

● 查看GPU队列状态的函数

extern __host__ cudaError_t CUDARTAPI cudaEventQuery(cudaEvent_t event);

■ stop为放置到流中的一个事件,cudaEventQuery(stop)返回该事件的状态,等于cudaSuccess(值等于0)表示已经发生;等于cudaErrorNotReady(值等于35)表示尚未发生。源代码中利用这段时间让CPU空转,记录了迭代次数。

while (cudaEventQuery(stop) == cudaErrorNotReady) counter++;

● stdlib.h 中关于返回成功和失败的宏

 #define EXIT_SUCCESS 0
#define EXIT_FAILURE 1

● 示例文件中的错误检查函数(定义在helper_cuda.h中),报告出错文件、行号、函数名,并且重启cudaDevice。

 #define checkCudaErrors(val)  check((val), #val, __FILE__, __LINE__)

 template< typename T >
void check(T result, char const *const func, const char *const file, int const line)
{
if (result)
{
fprintf(stderr, "CUDA error at %s:%d code=%d(%s) \"%s\" \n",
file, line, static_cast<unsigned int>(result), _cudaGetErrorEnum(result), func);
DEVICE_RESET// Make sure we call CUDA Device Reset before exiting
exit(EXIT_FAILURE);
}
} #define DEVICE_RESET cudaDeviceReset();

0_Simple__asyncAPI的更多相关文章

随机推荐

  1. Java随机数的使用

    在java中实现随机数的类有两种,分别是和java.util.Math 和 java.util.Random 第一种:java.lang.Math.random() Math.random()方法创建 ...

  2. P1034

    问题 E: P1034 时间限制: 1 Sec  内存限制: 128 MB提交: 29  解决: 22[提交][状态][讨论版] 题目描述 尼克每天上班之前都连接上英特网,接收他的上司发来的邮件,这些 ...

  3. BZOJ-1192-[HNOI2006]鬼谷子的钱袋

    Description 鬼谷子非常聪明,正因为这样,他非常繁忙,经常有各诸侯车的特派员前来向他咨询时政.有一天,他在咸阳游历的时候,朋友告诉他在咸阳最大的拍卖行(聚宝商行)将要举行一场拍卖会,其中有一 ...

  4. Iframe刷新页面

    window.parent.frames["name"].location="url";

  5. java中log4j学习笔记

    Log4j是apache的一个开源项目,用来操作程序日志信息的框架.因便于管理,在工程中用来代替System.out打印语句.通过配置Log4j中的log4j.properties,可以指定日志信息的 ...

  6. Java高新技术 注解

      Java高新技术 注解 知识概要:                  (1)了解注解 (2)注解的应用结构图 (3)@Retention(RetentionPolicy.RUNTIME)    ...

  7. 浅谈Java多态

    什么是Java中的多态?又是一个纸老虎的概念,老套路,把它具体化,细分化,先想三个问题(注意,这里不是简单的化整为零,而是要建立在学习一个新概念时的思考框架): 1.这个东西有什么用?用来干什么的?它 ...

  8. 【Java核心】ClassLoader原理及其使用

    又把博客的皮肤换了换,看着更加简洁舒心一些.前段的知识只是略懂,拿过来就能用,只是自己的审美和设计水平有限,实在难以弄出自己特别满意的东西,也算是小小的遗憾吧!言归正传,由于最近涉及到Java核心的东 ...

  9. Ricequant-米筐金工-估值因子

    Ricequant米筐金工--因子分析 作者:戴宇.小湖 上一篇介绍了单因子检验是因子分析前重要的一个步骤,是构建因子库.建立因子模型的基础,这篇报告首先对常见估值因子进行初步的检验. 第一篇.估值因 ...

  10. Oracle_11gR2_概念_第06章_数据字典和动态性能视图_英文词汇

    decode 解码 be intend for  适应 distinguished 显著的,突出的 implied 隐含的 abbreviated     简短的 enabled roles    已 ...