CUDA学习——函数

文章目录

  • 函数类型
  • 变量类型:
  • dim3结构类型
  • 常用的GPU内存函数
    • cudaMalloc()
    • cudaMemcpy()
    • cudaFree()
  • cuLaunchKernel()函数和<<<>>>

函数类型

device: 在device上执行,只能被device调用
global: 标示kernel函数,在device上执行,可以被host/device调用
host: 在host执行,只能被host调用
noinline: 函数不inline
forceinline:函数inline

变量类型:

device: device上的变量
constant: constant memory space上的变量
shared: shared memory,所有以这种形式声明的指针具有相同的起点
managed:host和device都可以读写的地址
restrict: 避免aliasing问题

dim3结构类型

  1. dim3是基亍uint3定义的矢量类型,相当亍由3个unsigned int型组成的结构体。uint3类型有三个数据成员unsigned int x; unsigned int y; unsigned int z;
  2. 可使用亍一维、二维或三维的索引来标识线程,构成一维、二维或三维线程块。
  3. dim3结构类型变量用在核函数调用的<<<,>>>中。
  4. 相关的几个内置变量
    4.1. threadIdx,顾名思义获取线程thread的ID索引;如果线程是一维的那么就取threadIdx.x,二维的还可以多取到一个值threadIdx.y,以此类推到三维threadIdx.z。
    4.2. blockIdx,线程块的ID索引;同样有blockIdx.x,blockIdx.y,blockIdx.z。
    4.3. blockDim,线程块的维度,同样有blockDim.x,blockDim.y,blockDim.z。
    4.4. gridDim,线程格的维度,同样有gridDim.x,gridDim.y,gridDim.z。
  5. 对于一维的block,线程的threadID=threadIdx.x。
  6. 对于大小为(blockDim.x, blockDim.y)的 二维 block,线程的threadID=threadIdx.x+threadIdx.y*blockDim.x。
  7. 对于大小为(blockDim.x, blockDim.y, blockDim.z)的 三维 block,线程的threadID=threadIdx.x+threadIdx.yblockDim.x+threadIdx.zblockDim.x*blockDim.y。
  8. 对于计算线程索引偏移增量为已启动线程的总数。如stride = blockDim.x * gridDim.x; threadId += stride。

常用的GPU内存函数

cudaMalloc()

  1. 数原型: cudaError_t cudaMalloc (void **devPtr, size_t size)。
  2. 函数用处:与C语言中的malloc函数一样,只是此函数在GPU的内存你分配内存。
  3. 注意事项:
    3.1. 可以将cudaMalloc()分配的指针传递给在设备上执行的函数;
    3.2. 可以在设备代码中使用cudaMalloc()分配的指针进行设备内存读写操作;
    3.3. 可以将cudaMalloc()分配的指针传递给在主机上执行的函数;
    3.4. 不可以在主机代码中使用cudaMalloc()分配的指针进行主机内存读写操作(即不能进行解引用)。

cudaMemcpy()

  1. 函数原型:cudaError_t cudaMemcpy (void *dst, const void *src, size_t count, cudaMemcpyKind kind)。
  2. 函数作用:与c语言中的memcpy函数一样,只是此函数可以在主机内存和GPU内存之间互相拷贝数据。
  3. 函数参数:cudaMemcpyKind kind表示数据拷贝方向,如果kind赋值为cudaMemcpyDeviceToHost表示数据从设备内存拷贝到主机内存。
  4. 与C中的memcpy()一样,以同步方式执行,即当函数返回时,复制操作就已经完成了,并且在输出缓冲区中包含了复制进去的内容。
  5. 相应的有个异步方式执行的函数cudaMemcpyAsync(),这个函数详解请看下面的流一节有关内容。

cudaFree()

  1. 函数原型:cudaError_t cudaFree ( void* devPtr )。
  2. 函数作用:与c语言中的free()函数一样,只是此函数释放的是cudaMalloc()分配的内存。

下面实例用于解释上面三个函数
C/C++ code

#include 
#include 
__global__ void add( int a, int b, int *c ) 
{    
	*c = a + b;
}
int main( void ) 
{    
	int c;    
	int *dev_c;    
	//cudaMalloc()    
	cudaMalloc( (void**)&dev_c, sizeof(int) );    
	//核函数执行    
	add<<<1,1>>>( 2, 7, dev_c );       
	//cudaMemcpy()    
	cudaMemcpy( &c, dev_c, sizeof(int),cudaMemcpyDeviceToHost ) ;    
	printf( "2 + 7 = %d\n", c );   
	 //cudaFree()    
	 cudaFree( dev_c );    
	 return 0;
}

cuLaunchKernel()函数和<<<>>>

在.Cu文件中,用__global__标识了内核。在CUDA运行时钟,它们可以使用由三对尖括号(<<<>>>)构成的单行代码启动,
模块中的GPU可执行代码以内核的形式呈现,或者使用CUDA运行时的语言集成特性启动(<<<>>>符号)或者使用驱动程序API中的cuLaunchKernel()函数启动。一旦模块被加载,内核可使用cuModuleGetFunction()函数查询,内核的属性使用cuFuncGetAttribute()函数查询,内核通过cuLaunchKernel()函数启动,cuLaunchKernel()包含了一整套已被废弃的API入口点:像cuFuncSetBlockShape()指定下次内核启动使用的线程块大小;函数cuParamSetv()指定下次内核启动传入的参数;cuLaunch()、cuLaunchGrid()和cuLaunchGridAsync()使用此前设置的状态启动内核。这些API很低效,因为这花费了太多的调用来启动一次内核,并且很多参数,像线程块大小,最好在每次请求内核启动时统一指定。函数cuFuncGetAttribute()可以被用来查询指定的属性,例如:
每线程块最大线程数
静态分配共享内存的数量
用户分配的常量内存大小
每个函数使用的本地内存数量
函数中每个线程使用的寄存器数量
被编译函数的虚拟(PTX)与二进制架构版本
当使用驱动程序API,最好使用extern C来禁止C++中的默认名称改编行为。否则,你必须对cuModuleGetFunction()使用改编的名称。

你可能感兴趣的:(Cuda,CUDA)