zoukankan      html  css  js  c++  java
  • CUDA[2] Hello,World

    Section 0:Hello,World

    这次我们亲自尝试一下如何用粗(CU)大(DA)写程序

    CUDA最新版本是7.5,然而即使是最新版本也不兼容VS2015 。。。推荐使用VS2012

    进入VS2012,新建工程,选择NVIDIA--CUDA Runtime

    我们来写一个简单的向量加法程序:[Reference]

     1 #include <stdio.h>
     2 
     3 __global__ void saxpy(int n, float a, float *x, float *y)   
     4 //__global__关键字,表示是将要在GPU里并行运行的核函数
     5 {
     6   int i = blockIdx.x*blockDim.x + threadIdx.x;
     7   if (i < n) 
     8     y[i] = a*x[i] + y[i];
     9 }
    10 
    11 int main()
    12 {
    13   int N = 10;
    14   float *x, *y, *d_x, *d_y;             //都是指针,指向数组所在的内存/显存空间
    15   x = (float*)malloc(N*sizeof(float));  //在内存中为x,y分配空间
    16   y = (float*)malloc(N*sizeof(float));
    17 
    18   cudaMalloc(&d_x, N*sizeof(float));    //在显存中为d_x,d_y分配空间
    19   cudaMalloc(&d_y, N*sizeof(float));
    20 
    21   for (int i = 0; i < N; i++) 
    22   {
    23     x[i] = (float)i;
    24     y[i] = 2.0f;
    25   }
    26 
    27   cudaMemcpy(d_x, x, N*sizeof(float), cudaMemcpyHostToDevice);  
    28   cudaMemcpy(d_y, y, N*sizeof(float), cudaMemcpyHostToDevice);
    29   //将内存中x,y指向的数组空间拷贝到显存中d_x,d_y指向的数组空间
    30 
    31   saxpy<<<1,N>>>(N, 10.0f, d_x, d_y);
    32   //1个block,每个block里N个thread
    33 
    34   cudaMemcpy(y, d_y, N*sizeof(float), cudaMemcpyDeviceToHost);  
    35   //将显存中计算好的d_y指向的数组空间拷贝到内存中y指向的数组空间
    36 
    37   for (int i = 0; i < N; i++)
    38     printf("%d  %.3f
    ",i,y[i]);
    39 
    40   getchar();
    41 }

    运行后就会出结果啦~

    Section 1:一个好一点的代码风格

    虽然刚才的程序已经能运行了,但是讲道理的话把所有的代码都写到cu文件里是很屎的风格。。。

    下面再来写一个向量加法的程序:[Ref]

     1 /*  kernel.cu   */
     2 //cuda系函数必须放在cu文件里
     3 #include "cuda_runtime.h"
     4 #include "device_launch_parameters.h"
     5 
     6 #include <stdio.h>
     7 
     8 __global__ void addKernel(int *c, const int *a, const int *b)
     9 {
    10     int i = threadIdx.x;
    11     c[i] = a[i] + b[i];
    12 }
    13 
    14 //cpp中不能直接调用核函数,所以在cu文件中还得写一个接口,负责分配内存等
    15 void addWithCuda(int *c, const int *a, const int *b, unsigned int size)
    16 {
    17     int *dev_a = 0;
    18     int *dev_b = 0;
    19     int *dev_c = 0;
    20 
    21     // Choose which GPU to run on, change this on a multi-GPU system.
    22     cudaSetDevice(0);
    23 
    24     // Allocate GPU buffers for three vectors (two input, one output)    .
    25     cudaMalloc((void**)&dev_c, size * sizeof(int));
    26     cudaMalloc((void**)&dev_a, size * sizeof(int));
    27     cudaMalloc((void**)&dev_b, size * sizeof(int));
    28 
    29     // Copy input vectors from host memory to GPU buffers.
    30     cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice);
    31     cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice);
    32 
    33     // Launch a kernel on the GPU with one thread for each element.
    34     addKernel<<<1, size>>>(dev_c, dev_a, dev_b);
    35 
    36     // Copy output vector from GPU buffer to host memory.
    37     cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost);
    38 
    39     cudaFree(dev_c);
    40     cudaFree(dev_a);
    41     cudaFree(dev_b);
    42     cudaDeviceReset();
    43 }
    44 
    45 //-------------------------------------------------------------------------------
    46 /* Source.cpp  */
    47 #include"cstdio"
    48 #include"cstring"
    49 
    50 extern void addWithCuda(int *c, const int *a, const int *b, unsigned int size);
    51 //.cpp是由C编译器来编译的。C编译器里不允许#include一个cu文件(不资词)
    52 //若要引用cu里的函数,在main.cpp里外部extern声明一下,让VS转为NVCC编译器处理。
    53 
    54 int main()
    55 {
    56     const int arraySize = 5;
    57     const int a[arraySize] = { 1, 2, 3, 4, 5 };
    58     const int b[arraySize] = { 10, 20, 30, 40, 50 };
    59     int c[arraySize] = { 0 };
    60 
    61     addWithCuda(c, a, b, arraySize);
    62 
    63     printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}
    ",
    64         c[0], c[1], c[2], c[3], c[4]);
    65 
    66     getchar();
    67 
    68     return 0;
    69 }

    补充:对于一些计算量较大(GPU计算时间较长)的程序,有可能运行很短时间之后就崩溃掉,并出现“显卡驱动已停止”的提示。

    这是因为驱动程序默认认为GPU只负责图形计算任务,如果有任务长时间占用GPU就会自动terminate掉。

    解决方法如下:[Ref]

    进入注册表->HKEY_LOCAL_MACHINE->System->CurrentControlSet->Control->GraphicsDrivers

    新建DWORD键TdrLevel,键值为0。保存重启即可。

    Section 2:还是要学习一个

    下面系统介绍一下粗大里的关键字和规则:

    [Ref]

    __global__:kernel函数。在device(GPU)里运行。可以在host(CPU处的主程序)调用

    __device__:只允许在device运行,在device调用

    __constant__:constant memory,表示常量

    __shared__:shared memory,block内共享的变量

  • 相关阅读:
    Git 历史/术语/命令/基本操作
    SQL 术语/语法/基本操作-必知必会
    bootstrap cdn地址
    IDEA 快捷键 大幅提高工作效率
    Django3 模版配置/过滤器/markdown=9
    Django3 路由文件位置/文件格式/路由传值=8
    Django3 创建项目/app全流程=7
    VS Code Django解决不必要报错
    Django3 如何使用静态文件/如何自定义后台管理页面=6
    Django3 如何编写单元测试和全面测试=5
  • 原文地址:https://www.cnblogs.com/pdev/p/5385117.html
Copyright © 2011-2022 走看看