1. CUDA的内存模型
每个线程有自己的私有本地内存local memory) , 每个线快有包含共享内存, 可以被线程块中所有线程共享,其声明周期与线程块一致。
此外,所有的线程都可以访问全局内存(global memory) 还可以访问一些只读内存块: 常量内存Constant Memory)和纹理内存(Texture Memory).
2. GPU的核心组件 – SM(Streaming Multiprocessor)
与CPU的多线程类似,一个Kernel实际上会启动很多线程,而多线程如果没有多核支持,在物理层也是无法实现并行的。
而GPU存在很多CUDA核心, 充分利用CUDA核心可以发挥GPU的并行计算能力。‘
SM的核心组件包括CUDA核心,共享内存,寄存器等,SM可以并发地执行数百个 线程,并发能力就取决与SM所拥有的资源数。
3.SIMI–(Single-Intruction, Multiple-Thread)单指令多线程
基本的执行单元是线程束(wraps),线程束包含32个线程,这些线程同时执行相同的指令,但是每个线程都包含自己的指令地址计数器和寄存器状态,也有自己独立的执行路径。
所以尽管线程束中的线程同时从同一程序地址执行,但是可能具有不同的行为,比如遇到了分支结构,一些线程可能进入这个分支,但是另外一些有可能不执行,它们只能死等,因为GPU规定线程束中所有线程在同一周期执行相同的指令,线程束分化会导致性能下降。
总之,就是网格和线程块只是逻辑划分,一个kernel的所有线程其实在物理层是不一定同时并发的。所以kernel的grid和block的配置不同
,性能会出现差异。另外,由于SM的基本执行单元是包含32个线程的线程束,所以block大小一般要设置为32的倍数。
4. 第一个CUDA示例,Cmake的配置等
#include <iostream>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>
void printDevicePropcudaDeviceProp& devProp, int dev)
{
std::cout << "使用GPU device " << dev << ": " << devProp.name << std::endl;
std::cout << "SM的数量:" << devProp.multiProcessorCount << std::endl;
std::cout << "每个线程块的共享内存大小:" << devProp.sharedMemPerBlock / 1024.0 << " KB" << std::endl;
std::cout << "每个线程块的最大线程数:" << devProp.maxThreadsPerBlock << std::endl;
std::cout << "每个EM的最大线程数:" << devProp.maxThreadsPerMultiProcessor << std::endl;
std::cout << "每个EM的最大线程束数:" << devProp.maxThreadsPerMultiProcessor / 32 << std::endl;
}
bool initCUDAcudaDeviceProp& devProp)
{
int count;
cudaGetDeviceCount&count);
ifcount == 0) {
return false;};
int i;
fori=0; i<count; i++)
{
ifcudaGetDeviceProperties&devProp, i) == cudaSuccess)
{
ifdevProp.major >= 1)
{
printDevicePropdevProp, i);
break;
}
}
}
ifi == count) {
std::cout<<"CUDA can't support the device !"<<std::endl; return false;};
cudaSetDevicei);
return false;
}
int main)
{
cudaDeviceProp devProp;
ifinitCUDAdevProp))
{
std::cout<<"CUDA initialized Succed. \n"<<std::endl;
}
//CHECKcudaGetDeviceProperties&devProp, dev));
return 0;
}
- CMakeLists.txt 的配置
cmake_minimum_requiredVERSION 3.1)
projectCUDA_Toturials)
setCMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11")
#set the default path for built executables to the "bin" directory
setCMAKE_BUILD_TYPE Debug)
setEXECUTABLE_OUTPUT_PATH ${
PROJECT_SOURCE_DIR}/bin)
SET LIBRARY_OUTPUT_PATH ${
PROJECT_SOURCE_DIR}/lib)
LINK_DIRECTORIES ${
PROJECT_SOURCE_DIR}/lib)
INCLUDE_DIRECTORIES ${
PROJECT_SOURCE_DIR}/include )
# openMp for parallel
# find_packageOpenMP)
# ifOPENMP_FOUND)
# setCMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
# setCMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
# endif)
find_packageCUDA 8.0 REQUIRED)
include_directories${
CUDA_INCLUDE_DIRS})
# 设置CUAD编译配置
setCUDA_NVCC_FLAGS "-g -G")
# build option
setGENCODE -gencode=arch=compute_35,code=sm_35)
setGENCODE ${
GENCODE} -gencode=arch=compute_30,code=sm_30)
setGENCODE ${
GENCODE} -gencode=arch=compute_20,code=sm_20)
setGENCODE ${
GENCODE} -gencode=arch=compute_10,code=sm_10)
setGENCODE ${
GENCODE} -gencode arch=compute_61,code=sm_61)
# 生成可执行文件
cuda_add_executablemain src/main.cpp)
# add_subdirectorysrc)