CUDA学习笔记1——核函数与线程

CUDA安装并配置环境后,使用VS新建工程时会出现对应选项:
在这里插入图片描述

CUDA核函数调用

  1. CUDA核函数必须用限定词 global 修饰,返回类型必须为void,二者次序随意。
  2. 函数名与()之间用三括号<<<网格大小,线程块大小>>>指明核函数中线程数目与排列情况;
  3. cudaDeviceSynchronize()函数用于同步主机与设备;
#include <stdio.h>
#include "cuda_runtime.h"

//如何调用cuda核函数
__global__ void first_kernel()
{
	printf("Hellow World GPU...\n");
}

int main()
{
	printf("Hellow World CPU  \n");

	first_kernel<<<2, 3>>>();
	cudaDeviceSynchronize();
	return 0;
}

在这里插入图片描述

CUDA核函数线程索引

  1. 每个核函数允许指派多个线程,线程的组织结构为:<<<grid_size, block_size>>>,乘积为线程总数
  • 对于大小为 ( D x , D y ) (D_x , D_y) (Dx,Dy)二维网络,线程的索引为(x,y),则这个线程的ID是 ( x + y ∗ D x ) (x + y * D_x) (x+yDx)
  • 对于大小为 ( D x , D y , D z ) (D_x , D_y, D_z) (Dx,Dy,Dz)三维网络,线程的索引为(x,y,z),则这个线程的ID是 ( x + y ∗ D x + z ∗ D x ∗ D y ) (x + y * D_x + z * D_x * D_y) (x+yDx+zDxDy)
一维网络

网格、线程块为一维

  • gridDim.x:数值为grid_size的数值
  • blockDim.x:数值为block_size的数值
  • blockIdx.x:线程在网格中的线程块ID,取值范围 0 ~ gridDim.x - 1;
  • threadIdx.x:线程在线程块中的线程ID,取值范围 0 ~ blockDim.x - 1;

例:

dim3 grid_size(4);//定义grid与block尺寸
dim3 block_size(8);

kernel_fun<<<grid_size,block_size>>>(...);//调用核函数

//计算线程索引
int id = blockIdx.x*blockDim.x+threadIdx.x;//线程块索引*线程块中线程的个数+线程在当前线程块中的索引

在这里插入图片描述

多维网络

网格、线程块为多维
dim3 grid_size(Gx,Gy,Gz);
dim3 block_size(Bx,By,Bz);

  • blockIdx.x:取值范围 0 ~ gridDim.x - 1;
  • blockIdx.y:取值范围 0 ~ gridDim.y - 1;
  • blockIdx.z:取值范围 0 ~ gridDim.z - 1;
  • threadIdx.x:取值范围 0 ~ blockDim.x - 1;
  • threadIdx.y:取值范围 0 ~ blockDim.y - 1;
  • threadIdx.z:取值范围 0 ~ blockDim.z - 1;

网格大小限制:x、y、z方向最大值为2^31-1、65535、65535

线程块大小限制:x、y、z方向最大值为1024、1024、64
其中,x维度是最内层(变化最快),z维度是最外层(变化最慢)

在这里插入图片描述
在这里插入图片描述

例:

dim3 grid_size(3,2);// 列优先
dim3 block_size(3,4);// 定义grid和block尺寸

kernel_fun<<< grid_size, block_size>>>(...);//调用核函数

//计算线程索引
int blockId = blockId.x + blockId.y*gridDim.x;//3=0+1*3
int threadId = threadIdx.y*blockDim.x+threadIdx.x;//10=3*3 + 1
//线程在网格中的唯一标识
int id = blockId*(blockDim.x*blockDim.y)+threadId;//46=3*(3*4) + 10

在这里插入图片描述

warpSize

warpSize为内建变量,表示线程束大小,对目前所以GPU架构warpSize=32;即一个线程束就是连续的32个线程。

#include <stdio.h>
#include "cuda_runtime.h"

//cuda核函数线程索引
__global__ void first_kernel()
{
	int tidx = threadIdx.x;
	int tidy = threadIdx.y;
	int tidz = threadIdx.z;
	int bidx = blockIdx.x;
	int bidy = blockIdx.y;
	int bidz = blockIdx.z;
	printf("GPU Kernel...thread index: (%d,%d), block index: (%d,%d) \n",  tidy, tidx, bidy, bidx);
}


int main()
{

	first_kernel<<<2, 3>>>();
	cudaDeviceSynchronize();
	return 0;
}


在这里插入图片描述

CUDA核函数要求总结

  1. 核函数返回类型必须是void;
  2. 必须使用限定符 _global_ ;
  3. 核函数支持重载;
  4. 不支持可变数量参数列表;
  5. 可向核函数传递非指针变量;
  6. 核函数不能为类的成员;
  7. 无论主机调用还是设备调用,核函数都是在设备中执行,调用时需指定执行配置;
  8. 计算能力3.5之前核函数之间不能相互调用,3.5开始引入动态并行机制,核函数可以相互调用;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值