NVIDIA® Tesla® P4 采用革命性的 NVIDIA Pascal™ 架构,8G支持10多路720P解码。
A卡指的是ATI,一个显卡厂商,但ATI被AMD收购之后,我们也把A卡称之为AMD显卡;N卡指的是NVIDIA(英伟达),另一个显卡厂商。N卡的GPU中每个流处理器都具有完整的ALU(算术逻辑单元)功能,在发出一条操作指令时每个流处理器都能充分工作。
而A卡的GPU中每个流处理器的5个流处理单元都是固定的,不能拆开重组。
而A卡的GPU中每个流处理器的5个流处理单元都是固定的,不能拆开重组。
最近cuda编程在AI行业应用较多,比较热。接触的两个应用。
应用一:
利用GPU进行视频编解码,比CPU要快很多。
购买Nvidia的显卡,然后安装在Dell服务器上,linux安装相应nivida驱动后,程序可以使用nvidia给出的视频编解码库进行视频编解码,不用学习cuda编程。
应用二:
人脸识别也使用到了GPU的并行计算能力。
Cuda与C语言类似,只是将很多C语言函数变成,“cuda”开头,另外cuda运行的核函数需要定义时增加宏头“__global__ ”。核函数在GPU上运行。cuda语言的编译为nvcc。
CPU与GPU间内存需要显示拷贝,经过PCI总线进行交互,这里可能会有瓶颈,尤其对多路视频并发。如果使用PCI-EX16标准,数据传输率为4.8GB/S。
cuda核心是任务分解。
启动核函数:
<<<>>>运算符对kernel函数完整的执行配置参数形式是<<<Dg, Db, Ns, S>>>
参数Dg用于定义整个grid的维度和尺寸,即一个grid有多少个block。为dim3类型。Dim3 Dg(Dg.x, Dg.y, 1)表示grid中每行有Dg.x个block,每列有Dg.y个block,第三维恒为1(目前一个核函数只有一个grid)。整个grid中共有Dg.x*Dg.y个block,其中Dg.x和Dg.y最大值为65535。
参数Db用于定义一个block的维度和尺寸,即一个block有多少个thread。为dim3类型。Dim3 Db(Db.x, Db.y, Db.z)表示整个block中每行有Db.x个thread,每列有Db.y个thread,高度为Db.z。Db.x和Db.y最大值为512,Db.z最大值为62。 一个block中共有Db.x*Db.y*Db.z个thread。计算能力为1.0,1.1的硬件该乘积的最大值为768,计算能力为1.2,1.3的硬件支持的最大值为1024。
参数Ns是一个可选参数,用于设置每个block除了静态分配的shared Memory以外,最多能动态分配的shared memory大小,单位为byte。不需要动态分配时该值为0或省略不写。
参数S是一个cudaStream_t类型的可选参数,初始值为零,表示该核函数处在哪个流之中。
一般只需使用前两个参数即可。
<<<>>>运算符对kernel函数完整的执行配置参数形式是<<<Dg, Db, Ns, S>>>
参数Dg用于定义整个grid的维度和尺寸,即一个grid有多少个block。为dim3类型。Dim3 Dg(Dg.x, Dg.y, 1)表示grid中每行有Dg.x个block,每列有Dg.y个block,第三维恒为1(目前一个核函数只有一个grid)。整个grid中共有Dg.x*Dg.y个block,其中Dg.x和Dg.y最大值为65535。
参数Db用于定义一个block的维度和尺寸,即一个block有多少个thread。为dim3类型。Dim3 Db(Db.x, Db.y, Db.z)表示整个block中每行有Db.x个thread,每列有Db.y个thread,高度为Db.z。Db.x和Db.y最大值为512,Db.z最大值为62。 一个block中共有Db.x*Db.y*Db.z个thread。计算能力为1.0,1.1的硬件该乘积的最大值为768,计算能力为1.2,1.3的硬件支持的最大值为1024。
参数Ns是一个可选参数,用于设置每个block除了静态分配的shared Memory以外,最多能动态分配的shared memory大小,单位为byte。不需要动态分配时该值为0或省略不写。
参数S是一个cudaStream_t类型的可选参数,初始值为零,表示该核函数处在哪个流之中。
一般只需使用前两个参数即可。
核函数需要计算线程ID,需要根据三维grid和三维block进行计算。这里不一一列举,参考:
- /**************************************************************/
- // !!!!!!!!!!!!!!注意!!!!!!!!!!!!!!!!
- /**************************************************************/
- // grid划分成a维,block划分成b维,
- // 等价于
- // blocks是a维的,Threads是b维的。
- // 这里,本人用的是第一中说法。
- /**************************************************************/
- // 情况1:grid划分成1维,block划分为1维。
- __device__ int getGlobalIdx_1D_1D() {
- int threadId = blockIdx.x *blockDim.x + threadIdx.x;
- return threadId;
- }
- // 情况2:grid划分成1维,block划分为2维。
- __device__ int getGlobalIdx_1D_2D() {
- int threadId = blockIdx.x * blockDim.x * blockDim.y
- + threadIdx.y * blockDim.x + threadIdx.x;
- return threadId;
- }
- // 情况3:grid划分成1维,block划分为3维。
- __device__ int getGlobalIdx_1D_3D() {
- int threadId = blockIdx.x * blockDim.x * blockDim.y * blockDim.z
- + threadIdx.z * blockDim.y * blockDim.x
- + threadIdx.y * blockDim.x + threadIdx.x;
- return threadId;
- }
- // 情况4:grid划分成2维,block划分为1维。
- __device__ int getGlobalIdx_2D_1D() {
- int blockId = blockIdx.y * gridDim.x + blockIdx.x;
- int threadId = blockId * blockDim.x + threadIdx.x;
- return threadId;
- }
- // 情况5:grid划分成2维,block划分为2维。
- __device__ int getGlobalIdx_2D_2D() {
- int blockId = blockIdx.x + blockIdx.y * gridDim.x;
- int threadId = blockId * (blockDim.x * blockDim.y)
- + (threadIdx.y * blockDim.x) + threadIdx.x;
- return threadId;
- }
- // 情况6:grid划分成2维,block划分为3维。
- __device__ int getGlobalIdx_2D_3D() {
- int blockId = blockIdx.x + blockIdx.y * gridDim.x;
- int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)
- + (threadIdx.z * (blockDim.x * blockDim.y))
- + (threadIdx.y * blockDim.x) + threadIdx.x;
- return threadId;
- }
- // 情况7:grid划分成3维,block划分为1维。
- __device__ int getGlobalIdx_3D_1D() {
- int blockId = blockIdx.x + blockIdx.y * gridDim.x
- + gridDim.x * gridDim.y * blockIdx.z;
- int threadId = blockId * blockDim.x + threadIdx.x;
- return threadId;
- }
- // 情况8:grid划分成3维,block划分为2维。
- __device__ int getGlobalIdx_3D_2D() {
- int blockId = blockIdx.x + blockIdx.y * gridDim.x
- + gridDim.x * gridDim.y * blockIdx.z;
- int threadId = blockId * (blockDim.x * blockDim.y)
- + (threadIdx.y * blockDim.x) + threadIdx.x;
- return threadId;
- }
- // 情况9:grid划分成3维,block划分为3维。
- __device__ int getGlobalIdx_3D_3D() {
- int blockId = blockIdx.x + blockIdx.y * gridDim.x
- + gridDim.x * gridDim.y * blockIdx.z;
- int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)
- + (threadIdx.z * (blockDim.x * blockDim.y))
- + (threadIdx.y * blockDim.x) + threadIdx.x;
- return threadId;
- }
参考:
http://blog.youkuaiyun.com/canhui_wang/article/details/51730264
http://blog.youkuaiyun.com/dcrmg/article/details/54850766