NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割
1、最小CUDA C程序在文件 hello.cu 中输入如下代码:
#include "stdio.h"int main(){ printf("Hello, world\n"); return 0;}
在我们的 安装了CUDA SDK的机器上,你可以使用以下命令进行编译:
(图片来自网络侵删)
$ nvcc hello.cu$ ./a.out
可以使用 -o 标志更改输出文件名: nvcc -o hello hello.cu
如果不想一直输入前面的 . (它指的是当前工作目录),可以编辑 .bashrc 文件,将当前目录添加到路径中:
export PATH=$PATH:.
不过有些人建议出于安全目的不要这样做。
2、使用核函数你可能认为这个程序是作弊,因为它实际上不使用任何 CUDA 功能,一切都在主机上运行。但是,重点是 CUDA C 程序可以完成常规 C程序可以做的所有事情。
下面是一个稍微有趣一点(但效率低下且仅用作示例)的程序,它使用核函数 add() 将两个数字相加:
#include "stdio.h"__global__ void add(int a, int b, int c){ c = a + b;}int main(){ int a,b,c; int dev_c; a=3; b=4; cudaMalloc((void)&dev_c, sizeof(int)); add<<<1,1>>>(a,b,dev_c); cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost); printf("%d + %d is %d\n", a, b, c); cudaFree(dev_c); return 0;}
请浏览上面的代码,它运行得更快!
考虑一下为什么?如果成功, cudaMalloc 将返回 cudaSuccess;可以检查以确保程序能够正确运行。
3、示例:向量求和这是一个简单的问题。给定两个向量(即数组),我们希望将它们相加到第三个数组中。例如:
A = {0, 2, 4, 6, 8}B = {1, 1, 2, 2, 1}
那么
C = A + B = {1, 3, 6, 8, 9}
在此示例中,数组长度为 5 个元素,因此我们创建 5 个不同的线程(thread)。
第一个线程负责计算 C[0] = A[0] + B[0]。第二个线程负责计算 C[1] = A[1] + B[1],依此类推。
以下是我们如何使用传统 C 代码执行此操作:
#include "stdio.h"#define N 10void add(int a, int b, int c){ int tID = 0; while (tID < N) { c[tID] = a[tID] + b[tID]; tID += 1; }}int main(){ int a[N], b[N], c[N]; // Fill Arrays for (int i = 0; i < N; i++) { a[i] = i, b[i] = 1; } add (a, b, c); for (int i = 0; i < N; i++) { printf("%d + %d = %d\n", a[i], b[i], c[i]); } return 0;}
这是两个数组求和的一种相当迂回的方法——我们这样做的原因是,这样可以更好地转换为 CUDA 版本。要编译和运行它,我们必须使用 g++(因为它使用了一些在 C 中不起作用的 C++ 样式符号)。
以下是 CUDA 版本:
#include "stdio.h"#define N 10__global__ void add(int a, int b, int c){ int tID = blockIdx.x; if (tID < N) { c[tID] = a[tID] + b[tID]; }}int main(){ int a[N], b[N], c[N]; int dev_a, dev_b, dev_c; cudaMalloc((void ) &dev_a, Nsizeof(int)); cudaMalloc((void ) &dev_b, Nsizeof(int)); cudaMalloc((void ) &dev_c, Nsizeof(int));// Fill Arrays for (int i = 0; i < N; i++) { a[i] = i, b[i] = 1; } cudaMemcpy(dev_a, a, Nsizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, Nsizeof(int), cudaMemcpyHostToDevice); add<<<N,1>>>(dev_a, dev_b, dev_c); cudaMemcpy(c, dev_c, Nsizeof(int), cudaMemcpyDeviceToHost); for (int i = 0; i < N; i++) { printf("%d + %d = %d\n", a[i], b[i], c[i]); } return 0;}
blockIDx.x 为我们提供 Block ID,范围从 0 到 N-1。如果我们改用 add<<<1,N>>> 会怎么样?然后我们可以通过 ThreadID 访问,即变量 threadIDx.x。
再举一个例子,让我们求两个 2D 数组的和。我们可以定义一个 2D 整数数组,如下所示:
int c[2][3];
以下代码说明了 2D 数组在内存中的布局方式:
for (int i=0; i < 2; i++) for (int j=0; j< 3; j++) printf("[%d][%d] at %ld\n",i,j,&c[i][j]);
输出如下:
[0][0] at 140733933298160[0][1] at 140733933298164[0][2] at 140733933298168[1][0] at 140733933298172[1][1] at 140733933298176[1][2] at 140733933298180
我们可以看到,我们有一个布局,其中 j 维中的下一个单元格占据内存中的下一个连续整数,其中一个 int 为 4 个字节:
一般来说,单元格的地址可以通过以下方式计算:
&c + [(sizeof(int) sizeof-j-dimension i] + (sizeof(int)) j
在我们的示例中,j 维的大小为 3。例如, c[1][1] 处的单元格将合并为:基地址 + (431) + (41) = &c+16。
如果我们使用数组表示法,C 将为我们进行寻址,因此如果 INDEX=iWIDTH + J那么我们可以通过以下方式访问元素: c[INDEX]
CUDA 要求我们将内存分配为一维数组,因此我们可以使用上面的映射到2D 数组。
为了使内核函数中的映射更容易一些,我们可以将块声明为与 2D 数组尺寸相同的网格。这将创建与数组宽度和高度相对应的变量 blockIdx.x 和 blockIdx.y 。
#include "stdio.h"#define COLUMNS 3#define ROWS 2__global__ void add(int a, int b, int c){ int x = blockIdx.x; int y = blockIdx.y; int i = (COLUMNSy) + x; c[i] = a[i] + b[i];}int main(){ int a[ROWS][COLUMNS], b[ROWS][COLUMNS], c[ROWS][COLUMNS]; int dev_a, dev_b, dev_c; cudaMalloc((void ) &dev_a, ROWSCOLUMNSsizeof(int)); cudaMalloc((void ) &dev_b, ROWSCOLUMNSsizeof(int)); cudaMalloc((void ) &dev_c, ROWSCOLUMNSsizeof(int)); for (int y = 0; y < ROWS; y++) // Fill Arrays for (int x = 0; x < COLUMNS; x++) { a[y][x] = x; b[y][x] = y; }cudaMemcpy(dev_a, a, ROWSCOLUMNSsizeof(int), cudaMemcpyHostToDevice); cudaMemcpy(dev_b, b, ROWSCOLUMNSsizeof(int), cudaMemcpyHostToDevice); dim3 grid(COLUMNS,ROWS); add<<<grid,1>>>(dev_a, dev_b, dev_c); cudaMemcpy(c, dev_c, ROWSCOLUMNSsizeof(int), cudaMemcpyDeviceToHost); for (int y = 0; y < ROWS; y++) // Output Arrays { for (int x = 0; x < COLUMNS; x++) { printf("[%d][%d]=%d ",y,x,c[y][x]); } printf("\n"); } return 0;}
原文链接:CUDA C 开发入门 - BimAnt