CUDA C++ / 基础编程
核函数
作用
调用核函数的时候,代码会被N个CUDA线程执行N次。
修饰符
__global__ 返回值 函数名(){
...执行代码
}
调用
函数名<<<BlockNumber,ThreadNumber>>>();
BlockNumber是块的个数。
ThreadNumber是每一个块中的线程个数。
索引结构
块内线程的索引结构(threadIdx)
在一维,二维,三维的块中,threadIdx分别为一维索引,二维索引,三维索引。
threadIdx.x:一维索引
threadIdx.y:二维索引
threadIdx.z:三维索引
网内块的结构(blockIdx)
在一维,二维,三维的网中,blockIdx分别为一维索引,二维索引,三维索引。
blockIdx.x:一维索引
blockIdx.y:二维索引
blockIdx.z:三维索引
blockDim:块的大小(块内线程总数)
向量元素与线程之间映射
一维
blockIdx.x * blockDim.x + threadIdx.x
假设有Item0,Item1,Item2,Item3,Item4,Item5,Item6,Item7八个元素。有两个块block1,block2,每个块4个线程。则分配如下
Item0,Item1,Item2,Item3,分配给block1中的0,1,2,3号线程。
Item4,Item5,Item6,Item7,分配给block2中的0,1,2,3号线程。
则block2中的3号线程处理的元素,根据公式得:1*4+3=7,也就是Item7(索引下标从0开始)
三维
threadIdx.z * blockDim.y * blockDim.x + threadIdx.y * blockDim.x + threadIdx.x
网格大小与工作量匹配
匹配情况
每一个线程对应一个元素
不匹配
元素个数与线程总数不匹配,导致有的线程没有工作可干,运行时会出错。
解决方法
将任务总数N传递到核函数中。
网格内的线程,利用 threadIdx + blockIdx*blockDim检查自己是否超过元素总数N。
跨网格工作
通常一个线程不是处理一个元素,而是处理多个元素。
因此每次增长的步长为blockDim.x * gridDim.x(也就是一个网格的所有线程数)
此网格的块数GridDim.x为2,块中的线程数blockDim.x为4,所以一个网格的线程总数为2*4
案例
计算10000个元素,使用256个块,每个块32个线程,一轮可以处理8192个元素。那么在第二轮的时候,只需要判断i增加了后是否超过N即可,超过N的线程不执行。
__global__ void doubleElements(int *a, int N)
{
int i;
i = blockIdx.x * blockDim.x + threadIdx.x;
int stride= blockDim.x * gridDim.x;
for(;i<N;i+=stride){
if (i < N)
{
a[i] *= 2;
}
}
size_t threads_per_block = 256;
size_t number_of_blocks = 32;
doubleElements<<<number_of_blocks, threads_per_block>>>(a, N);
线程同步
块内同步函数
void __syncthreads();
阻塞块内所有线程,当所有线程到达__syncthreads()才会继续往下执行
host端同步函数
cudaDeviceSynchronize();
每次启动核函数后调用该函数,可以保证核函数完成,再继续当前线程。
本文来自博客园,作者:Laplace蒜子,转载请注明原文链接:https://www.cnblogs.com/RedNoseBo/p/17063325.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了