CUDA (or Compute Unified Device Architecture) is a parallel computing platform and application programming interface (API) that allows software to use certain types of graphics processing unit (GPU) for general purpose processing – an approach called general-purpose computing on GPUs (GPGPU). CUDA is a software layer that gives direct access to the GPU's virtual instruction set and parallel computational elements, for the execution of compute kernels. CUDA is designed to work with programming languages such as C, C++, and Fortran. This accessibility makes it easier for specialists in parallel programming to use GPU resources, in contrast to prior APIs like Direct3D and OpenGL, which required advanced skills in graphics programming. CUDA-powered GPUs also support programming frameworks such as OpenMP, OpenACC and OpenCL; and HIP by compiling such code to CUDA. CUDA was created by Nvidia. When it was first introduced, the name was an acronym for Compute Unified Device Architecture, but Nvidia later dropped the common use of the acronym.
中文版(谷歌翻译):
1 2 3
CUDA(或Compute Unified Device Architecture)是一种并行计算平台和应用程序编程接口(API),它允许软件使用某些类型的图形处理单元(GPU)进行通用处理——这种方法称为GPU上的通用计算(GPGPU) )。 CUDA 是一个软件层,可以直接访问 GPU 的虚拟指令集和并行计算元素,以执行计算内核。 CUDA 旨在使用 C、C++ 和 Fortran 等编程语言。这种可访问性使并行编程专家可以更轻松地使用 GPU 资源,这与 Direct3D 和 OpenGL 等需要高级图形编程技能的先前 API 形成鲜明对比。 CUDA 驱动的 GPU 还支持 OpenMP、OpenACC 和 OpenCL 等编程框架; 和 HIP 通过将此类代码编译为 CUDA。 CUDA 是由 Nvidia 创建的。 首次引入时,该名称是 Compute Unified Device Architecture 的首字母缩写词, 但 Nvidia 后来放弃了该首字母缩写词的常见用法。
#include<stdio.h> #include<stdlib.h> #include<iostream> #include<time.h> #include"cuda_runtime.h" #include"device_launch_parameters.h" constint maxn = 1000000; // 元素值上限 - 一百万 constint maxl = 1000000; // 数组长 - 一百万 int* h_a, * h_b, * h_sum, * h_cpusum, tot = 0; // 数据指针 clock_t pro_start, pro_end, sum_start, sum_end; // CPU 时钟计数 cudaEvent_t e_start, e_stop; // CUDA 性能测试点 __global__ voidnumAdd(int* a, int* b, int* sum){ int i = threadIdx.x + blockIdx.x * blockDim.x; sum[i] = a[i] + b[i]; } intmain(){ srand(time(0)); // 设定随机数种子 h_a = newint[maxl], h_b = newint[maxl], h_sum = newint[maxl], h_cpusum = newint[maxl]; // 动态分配内存 pro_start = clock(); for (int i = 0; i < maxl; ++i) { h_a[i] = rand() % maxn; h_b[i] = rand() % maxn; // 初始化随机数据 } pro_end = clock(); // 输出 生成随机数 用时 (由于 CUDA 上无法完成随机数的初始化,遂不进行对比) printf("produce %d random number to two array use time : %0.3f ms\n", maxl, double(pro_end - pro_start) / CLOCKS_PER_SEC * 1000); system("pause"); int* d_a, * d_b, * d_sum; cudaEventCreate(&e_start); cudaEventCreate(&e_stop); // 创建 CUDA 事件 cudaEventRecord(e_start, 0); // 记录 CUDA 事件 // 在显存上分配单元 cudaMalloc((void**)&d_a, sizeof(int) * maxl); cudaMalloc((void**)&d_b, sizeof(int) * maxl); cudaMalloc((void**)&d_sum, sizeof(int) * maxl); /*printf("memory allocated!\n");*/ // 拷贝内存数据到显存 cudaMemcpy(d_a, h_a, sizeof(int) * maxl, cudaMemcpyHostToDevice); cudaMemcpy(d_b, h_b, sizeof(int) * maxl, cudaMemcpyHostToDevice); /*printf("copy finished!\n");*/ numAdd << <1000, 1000 >> > (d_a, d_b, d_sum); // 调用 Kernel 函数传入参数并执行代码 cudaDeviceSynchronize(); // 同步GPU上的所有线程,等待所有线程结束后再继续 /*printf("sum finished!\ncopy backing...\n");*/ cudaMemcpy(h_sum, d_sum, sizeof(int) * maxl, cudaMemcpyDeviceToHost); // 从显存拷贝结果数据到内存 /*printf("copy backed!\n");*/ cudaFree(d_a); cudaFree(d_b); cudaFree(d_sum); // 释放GPU上分配的显存 /*printf("device RAM released!\n");*/ cudaEventRecord(e_stop, 0); cudaEventSynchronize(e_stop); // 记录用时 float elapsedTime; cudaEventElapsedTime(&elapsedTime, e_start, e_stop); printf("CUDA sum use time : %0.3f ms\n", elapsedTime); sum_start = clock(); for (int i = 0; i < maxl; ++i) h_cpusum[i] = h_a[i] + h_b[i]; // CPU 进行加法计算 sum_end = clock(); printf("CPU sum use time : %0.3f ms\n", double(pro_end - pro_start) / CLOCKS_PER_SEC * 1000); for (int i = 0; i < maxl; ++i) if (h_cpusum[i] != h_sum[i]) ++tot; // 检验 CPU 计算结果 与 GPU 计算结果是否一致,统计不一致个数 printf("error sum num : %d\n", tot); system("pause"); delete h_a; delete h_b; delete h_sum; // 释放内存 return0; }
博主使用的机器是 i9-9900k 以及 Nvidia RTX 2070 最后运行性能表现如下:
1 2 3 4 5 6
produce 1000000 random number to two array use time : 69.000 ms 请按任意键继续. . . CUDA sum use time : 3.444 ms CPU sum use time : 69.000 ms error sum num : 0 请按任意键继续. . .
那么在这台机器上 GPU 性能比 CPU 足足高出 20倍 那么有同学可能就要问了, 说好 ʘ(n) 变 ʘ(1) 的呢? 是这样的,上述代码在测量 GPU 性能时包含了数据从内存经总线传输到显存上的用时 而且,测量 CPU 用时使用的是 CPU 时钟计,这个是不准确的,严格来说,CPU 用时应该更长
总结
CUDA 可以加速一些简单但量大的操作
CUDA 适合处理图像
CUDA 程序的标准工作流程是
分配显存单元
从内存拷贝数据到显存
通知显卡开始计算
拷贝结果数据回主机
使用结果数据
另外小小吐槽一下:博主同时安装了 VS 2022 和 VS 2019,因为 Nvidia 目前还没有将 CUDA 的开发包扩展迁移到 VS 2022 上,博主不得不又安装了 VS 2019 那么问题是,在 VS 2019 和 VS 2022 中设置主题是冲突的 例如, 博主的 VS 2022 使用的 NightOwl 主题, 当我设置 VS 2019 为深色主题时, VS 2022 会变成默认的蓝色主题 探究后发现,NightOwl 主题也是基于深色主题的,当两个版本的 IDE 设置为同一个根主题时,主题就会冲突………… 就,挺影响的🤣