NVIDIA ®  Tesla ®  P4 采用革命性的 NVIDIA Pascal™ 架构,8G支持10多路720P解码。


A卡指的是ATI,一个显卡厂商,但ATI被AMD收购之后,我们也把A卡称之为AMD显卡;N卡指的是NVIDIA(英伟达),另一个显卡厂商。N卡的GPU中每个流处理器都具有完整的ALU(算术逻辑单元)功能,在发出一条操作指令时每个流处理器都能充分工作。
而A卡的GPU中每个流处理器的5个流处理单元都是固定的,不能拆开重组。



最近cuda编程在AI行业应用较多,比较热。接触的两个应用。


应用一:


利用GPU进行视频编解码,比CPU要快很多。


购买Nvidia的显卡,然后安装在Dell服务器上,linux安装相应nivida驱动后,程序可以使用nvidia给出的视频编解码库进行视频编解码,不用学习cuda编程。


应用二:


人脸识别也使用到了GPU的并行计算能力。



__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类型的可选参数,初始值为零,表示该核函数处在哪个流之中。

一般只需使用前两个参数即可。




核函数需要计算线程ID,需要根据三维grid和三维block进行计算。这里不一一列举,参考:

1. /**************************************************************/  
2. // !!!!!!!!!!!!!!注意!!!!!!!!!!!!!!!!  
3. /**************************************************************/  
4. // grid划分成a维,block划分成b维,  
5. // 等价于  
6. // blocks是a维的,Threads是b维的。  
7. // 这里,本人用的是第一中说法。  
8. /**************************************************************/  
9.   
10.   
11. // 情况1:grid划分成1维,block划分为1维。  
12. __device__ int getGlobalIdx_1D_1D() {  
13. int threadId = blockIdx.x *blockDim.x + threadIdx.x;  
14. return threadId;  
15. }  
16.   
17. // 情况2:grid划分成1维,block划分为2维。  
18. __device__ int getGlobalIdx_1D_2D() {  
19. int threadId = blockIdx.x * blockDim.x * blockDim.y  
20.         + threadIdx.y * blockDim.x + threadIdx.x;  
21. return threadId;   
22. }  
23.   
24. // 情况3:grid划分成1维,block划分为3维。  
25. __device__ int getGlobalIdx_1D_3D() {  
26. int threadId = blockIdx.x * blockDim.x * blockDim.y * blockDim.z  
27.         + threadIdx.z * blockDim.y * blockDim.x  
28.         + threadIdx.y * blockDim.x + threadIdx.x;  
29. return threadId;  
30. }  
31.   
32. // 情况4:grid划分成2维,block划分为1维。  
33. __device__ int getGlobalIdx_2D_1D() {  
34. int blockId = blockIdx.y * gridDim.x + blockIdx.x;  
35. int threadId = blockId * blockDim.x + threadIdx.x;  
36. return threadId;  
37. }  
38.   
39. // 情况5:grid划分成2维,block划分为2维。  
40. __device__ int getGlobalIdx_2D_2D() {  
41. int blockId = blockIdx.x + blockIdx.y * gridDim.x;  
42. int threadId = blockId * (blockDim.x * blockDim.y)  
43.         + (threadIdx.y * blockDim.x) + threadIdx.x;  
44. return threadId;  
45. }  
46.   
47. // 情况6:grid划分成2维,block划分为3维。  
48. __device__ int getGlobalIdx_2D_3D() {  
49. int blockId = blockIdx.x + blockIdx.y * gridDim.x;  
50. int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  
51.         + (threadIdx.z * (blockDim.x * blockDim.y))  
52.         + (threadIdx.y * blockDim.x) + threadIdx.x;  
53. return threadId;  
54. }  
55.   
56. // 情况7:grid划分成3维,block划分为1维。  
57. __device__ int getGlobalIdx_3D_1D() {  
58. int blockId = blockIdx.x + blockIdx.y * gridDim.x  
59.         + gridDim.x * gridDim.y * blockIdx.z;  
60. int threadId = blockId * blockDim.x + threadIdx.x;  
61. return threadId;  
62. }  
63.   
64. // 情况8:grid划分成3维,block划分为2维。  
65. __device__ int getGlobalIdx_3D_2D() {  
66. int blockId = blockIdx.x + blockIdx.y * gridDim.x  
67.         + gridDim.x * gridDim.y * blockIdx.z;  
68. int threadId = blockId * (blockDim.x * blockDim.y)  
69.         + (threadIdx.y * blockDim.x) + threadIdx.x;  
70. return threadId;  
71. }  
72.   
73. // 情况9:grid划分成3维,block划分为3维。  
74. __device__ int getGlobalIdx_3D_3D() {  
75. int blockId = blockIdx.x + blockIdx.y * gridDim.x  
76.         + gridDim.x * gridDim.y * blockIdx.z;  
77. int threadId = blockId * (blockDim.x * blockDim.y * blockDim.z)  
78.         + (threadIdx.z * (blockDim.x * blockDim.y))  
79.         + (threadIdx.y * blockDim.x) + threadIdx.x;  
80. return threadId;  
81. }