cuda注意

1,不能在主机代码中对cudamalloc()返回的指针进行解应用,主机代码可以将这个指针作为参数传递,对其进行算术运算,甚至可以将其转换为另一种不同的类型,但是,不可使用这个指针来读取或者写入内存;

2,主机指针只能访问主机代码中的内存,而设备指针也只能访问设备代码中的内存;

3,memPitch:在内存复制中最大的修正量,单位是字节,在cudaDeviceProp中的字段。作用;

4,GPU中通常使用的分配内存的方式使用cudamalloc,但是对于二维和三维的矩阵而言,使用cudaMalloc来分配内存并不能的得到最后的性能,原因是:对于二维和三维的内存,对齐是一个很重要的性质,cudaMallocPitch或者cudaMalloc3D这两个函数能够保证分配的怒才能是合理对齐的,满足物理上的内存访问。可以确保对行访问时具有最优的效率。除此之外,应当使用cudaMemcpy2D和cudaMemcpy3D来实现,

2)cudaMallocPitch()的使用:float *dc_mat = (float*)malloc(sizeof(float)*M*N);  size_t pitch; cudaMallocPitch(&d_mat,&pitch,M*sizeof(float),N);之后调用kernel函数,将数据拷贝出来;cudaMemecpy2D(dc_mat,M*sizeof(float),d_mat,pitch,M*sizeof(float),N,cudaMemcpyToHost);这里的pitch是一行内存的大小,即M*sizeof(float)

5,根据设备的属性可以选择使用最多处理器的GPU来执行代码,

6,GPU的计算功能在1.3或者更高的显卡才能支持双精度的数学计算

7,在设备查询到时候,一种是直接通过迭代的方式举个设备获得设备信息,另一种是:cudaDeviceProp prop;int dev   cudaGetDevice(&dev);  之后给prop对应的字段赋值:

memset(&prop,0,sizeof(cudaDeviceProp));prop.major = 1;prop.minor = 3;   之后通过cudaChooseDevice(&dev,&prop),返回匹配设备的编号,之后就选择对应的设备:cudaSetDevice(dev);

8,在核函数中分配的块数,<<<N,1>>>在GPU上是并行进行的,GPU将运行的核函数的N 个副本,在代码中通过blockIdx.x.来说明是哪个线程块在执行。并行线程块的集合称为一个线程格。线程块的每一维最大不能超过65535,这是一种硬件限制。超过了这个范围,就会导致程序运行失败。

9,dim3 grid(DIM ,DIM )用于指定启动的指定的线程块的数量,

10,共享内存与同步:共享内存:GPU上启动的每一个线程块,都将创建该变量的一个副本,线程块中的每个线程都共享这块内存,但是线程不能修改其他线程块中的变量副本,

这样,一个线程块中的多个线程可以进行通信和协作。共享内存留在GPU上,延迟要第很多,

11,规约算法,树状加法(在深入浅出cuda中);

12,每个multiprocessor对应一个block,每个multiprocessor有8个stream processor,;要计算分配的块数,1)先得到GPU有多少个流多处理器,2)每个流多处理器有多少的寄存器,3)每个线程需要多少寄存器,得到每个块中分配多少线程;每个线程块中的线程是32的倍数,符合warp为32的要求,

13,3.7 寄存器
寄存器是NVIDIA GPU存储器空间中,最快的硬件,读取它几乎不用耗费时间。因此合理的使用它是至关重要的。

3.7.1 寄存器溢出和本地存储器
由于GPU上寄存器的数目是有限的,在计算能力1.0,1.1的设备上,其数目是8 K,在计算能力1.2,1.3的设备上,其值是16 K。如果我们使用的寄存器数目超过了系统的最大数目,编译器便会将其转入设备存储器上的一个区域内,这个区域称为本地存储器。本地存储器的速度和全局存储器一样。
使用2.3及以前的toolkit,可以使用-keep指令输出中间文件,然后直接查看cubin文件就可以知道内核使用的寄存器数目,同时也能看到共享存储器、常量存储器和本地存储器的使用量。如果使用的是3.0的toolkit,此时cubin文件已经不是文本格式,因此不能直接查看,此时可以在用nvcc 编译的时候,使用—ptxas-options=-v选项,编译器会报告存储器使用信息。

3.8 执行配置和占用率
使用<<<grid, block>>>语法指定执行线程配置的时候,grid 和block大小也影响程序的效率。一般而言,grid要大于多处理器的数目,这样才能让多处理器不至于空闲,但是这样也会导致一些问题,比如负载均衡,如果grid大小不能比sm 数目整除的话,就会有SM计算的时候,另外一些SM空闲,如果grid远大于sm数目的话,可忽略,但是如果SM数目与grid大小相差不大的话,性能损耗就很可观了。一般而言,grid大小至少是sm数目的三倍,如果有块内同步的话,grid要data_len大于sm的四倍以上。一般而言,block大小要是束大小的四倍以上,此时基本上可隐藏访存延迟。如果数据量比较小的话,grid大小和block大小可能相互牵制,此时要综合考虑。在数据量比较大的时候,只要考虑block大小就行了。
另外,CUDA还有一个占用率问题,所谓占用率就是SM上活跃块数目和最大允许数目的比例。使用cuda visual profiler的时候会有这个值。这个值的影响因素有内核内寄存器、共享存储器的用量。由于CUDA线程在切换的时候并不转储线程的状态,这是CUDA线程极轻的原因,但是这也使得为了保证线程能够切换,内核内使用的资源最多只能是最大资源的一半,此时占用率是0.25,一般而言占用率要在0.5左右就可以了。


14,__shared__ int data[] :共享内存是以4bytes为单位分成banks,那么:data[0]位data[0]依次类推

15,常量内存用于保存在内核函数执行期间不会发生变化的数据。在某些情况下,用常量内存来替换全局内存能有效的减少内存带宽。、

16,告诉CPU在某个事件上同步,这个事件是cudaEventSynchronize();

17,案例:cudaEvent_t start,stop;  创建事件
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);  记录开始时间

执行的事件

      cudaEventRecord(stop,0);
cudaEventSynchronize(stop);  确保所有的GPU事件都执行完了
float elapsedTime;
HANDLE_ERROR(cudaEventElapsedTime(&elapsedTime,start,stop)); 记事件的时间。
printf("the time of before mid_data is %f\n",elapsedTime);
HANDLE_ERROR(cudaEventDestroy(start));销毁事件。防止内存泄露
HANDLE_ERROR(cudaEventDestroy(stop));


18,cuda写循环慢:GPU中有成千上万的线程的吞吐量可以提升速度,但是其中每个线程的运算功能要比cpu慢。CPU擅长处理循环。,

19,常量内存提高性能:对常量内存的单次读取操作可以广播到其他的“邻近”线程,这将节约15次读取操作

2)常量内存的数据将缓存起来,因此对于相同地址的连续操作将不会产生额外的内存通信量。

在函数外定义常量:__constant__ int num[size];     在主函数中使用cudaMemcpyToSymbol(num,src,size);之后在内车函数中使用就可以了。不用在设备和host之间传播。

20,纹理内存:在特定的访问模式中,纹理内存同样能够提升性能并减少内存流量。

2)纹理存储器的声明的大小比常数存储器要大的多。在kernel中访问纹理存储器的操作称为纹理拾取,将显卡中的数据与纹理参照系关联的操作,称为将数据与纹理绑定。

显存中可以绑定到纹理的数据有两种:分为普通的线性存储器和cuda数组。

线性存储器只能与1,2维的纹理绑定,采用整型纹理拾取坐标,坐标值与数据在存储器中的位置相同。

CUDA数组可以与一维和二维和三维纹理绑定,纹理拾取坐标为归一化或者非归一化的浮点型,并且支持许多特殊功能。

纹理缓存中的数据可以被重复利用

纹理缓存一次预取拾取坐标对应位置附近的几个像元,可以实现滤波模式、。

21,有文件表名:的那个线程块的数量为GPU中处理器数量(流多处理器)的2倍的时候,将达到最佳性能。

22.__syncthreads():是cuda的内置函数,头文件为device_function.h.保证block块中可以到达的都到达了。最重要的理解是那些可以到达__syncthreads()的线程需要其他可以到达该点的线程,而不是等待块内所有其他线程。

23,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野狼位位

给点辛苦费0.1元

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值