global memory的访问

请教几个问题:
1.global memory上的二维数组a_d(100,100),CPU端直接赋值a_d=0的机制是什么,是同时把10000个element赋值0吗?为什么比做一个二维循环把a的element一个个赋值0要快很多。 那是不是相当于循环操作赋值(后者)是前者需要时间的一万倍?
2.还是用线程来赋初值?一个线程对应一个element,赋值=0,和CPU的代码a_d=0从机理上讲那种会快点?

特别感谢论坛版主每个帖子都耐心的解答,受益匪浅~

LZ您好:

没有太看明白您所说的“CPU端直接赋值a_d=0”是什么意思。

一般对global memory上的空间清零有3种方法:
1:使用cudaMemset(),这个是runtime API提供的函数,使用较为简便。以及,我并不清楚其实现机制,请向NV原厂支持继续询问。

2:写一个kernel对一段global memory清零,这个就是普通的kernel而已,以及效率也较高。

3:在host上申请一个等大的数组,用CPU循环对此缓冲区清零/使用memset()函数对此缓冲区清零,将此缓冲区使用cudaMemcpy()复制给global memory里面的数组。

一般不使用第三种方法。第一种方法比较简洁,可以使用,但是在使用异步版本的cudaMemcpy类函数的时候,cudaMemset()可能会影响异步版本的copy函数的异步行为,此时建议使用第二种方法,使用kernel清零。

大致如此,供您参考,祝您编码顺利~

嗯嗯。我深刻赞同ICE的观点。

实际上,楼主您无法在host上使用d_a = 0来清零一段global memory的。您听谁说的这个可以?

感谢两位版主回答~

请教一下,什么是异步版本的cudaMemcpy类函数?使用 cudaMemset() 后,要同步一下吗?怎么同步?谢谢啦!

您好:

1:以Async结尾的cudaMemcpy类的函数是所谓“异步版本”。

2:cudaMemset()是对于host的异步函数,一般无需同步的。以及您可以用cudaDeviceSynchronize()同步所有GPU的任务,当然也包括cudaMemset()。

大致如此,祝您编码顺利~