滚动新闻:
首页 > 客户服务 > 技术支持

Ubuntu环境下的CUDA编程(三)

  一、出现了 shared data 过多的现象

  在编译的时候,Kernel调用的那一行报错,说是用了过多的 share data,程序出错,本来以为时参数过多,后来才发现,计算的时候不小心将每个 block 里面 shared data 分配过多,超过了每个 block 中 shared memory 的总数,所以报错,修改 BLOCK_SIZE 以后,错误消失。

  二、使用没有分块的矩阵乘法比分块了的还要快

  分块矩阵使用了 shared memory 加速,按道理是应该更快的,但是,实际测试出来的数据却非常接近,而且没有分块的算法甚至快了一点,不可思议,检查了几次代码,都没有发现什么问题,过程完全合理,只是结果实在不合理,没办法,输出结果查看是否都一样。

  结果显示,两个函数都没有计算正确,果然,矩阵的乘积结果根本就没有输出,用于存储结果的那个矩阵一点都没有改变,说明要不就是 Kernel 根本没有执行,要不就是复制函数执行失败,那么,使用CUT_CHECK_ERROR() 来检测错误吧。

  错误显示一:Kernel 执行之前已经有 out of memory,内存溢出

  错误显示二:复制函数那一行出现了 invalid parameter,无效的参数

  马上检查矩阵规模,仔细计算,发现,果然GPU的内存溢出了,将矩阵规模改小,上述错误同时消失,输出矩阵乘积结果,终于正常了,测试时间,也正常了,大概可以加速3倍(BLOCK_SIZE = 16)。

  三、计算时间与复制时间的差异

  将计算语句与复制语句分开及时,使用 clock() 函数读取 CPU 时间,再除以 CLOCKS_PER_SEC ,得到以秒为单位的时间,这个时候,发现总时间没有问题,但是,计算时间随着矩阵乘法核函数调用次数(我使用了一个循环调用)的增加根本就没有变化,反倒是复制时间差不多随着相同倍数增加了,有违常理,那么,每一个时间记录在更新的时候都输出一次来查看它们的变化吧。

  查看结果为:在循环调用 Kernel 之前,一切正常,但是,循环所用的计算时间极短,可是接下来的复制时间却极长,此时不由得想到了 Kernel 在还没有运行结束之前,可能已经调用了下面的两个计时函数,导致一个提前结束,一个提前开始,所以,最好在调用计时函数的时候先保证 Kernel 已经执行完毕。

  使用函数:CUDAThreadSynchronize();来强制让Kernel函数在调用计时函数之前一定要完成,再次测试,结果正常,复制时间稳定,计算时间随着循环次数相应增长。

 

  另外:第一次调用 Kernel 的时间会特别长(包含了启动时间),所以,循环之前要先调用一次 Kernel 以保证GPU处于工作状态。