常量内存的使用问题

空间中有两个点集S1和S2,现在要做的是给S1中的每一个点A[i],在S2中找到离它距离最近的点
我现在的做法是 启用的线程数与S1中的点数相同,在Kernel中用循环遍历S2中的点,依次求出A[i]到S2中每个点距离,并进行比较,保存最短的距离和S2中最近点的编号。
(1)当S1和S2中点的数据量都不是很大时,我把这两个点集的坐标都放在常量内存中,在Kernel中进行访问
(2)但当数据量较大,常量内存不足以存放时,我就不保存S1和S2中的点的坐标,而是在Kernel中先根据线程号计算得到点的坐标,然后计算距离,再比较,最终得到最短的距离和最近点的编号(点的坐标和序号之间有一定的对应关系,但是这个关系计算起来也相当麻烦,也就是说根据线程号得到点的坐标的计算量也挺大的)
我想问的是,数据量较少时,我把数据都存放在常量内存中,这样是不是最快的方法,当数据量大时,我还是想通过常量内存进行计算,这样的想法是不是正确,怎么做才是最好的方法?
这个问题,实际上是Voronoi计算的问题,请研究比较深入的高手给解释一下,万分感谢!

LZ您好:

对Voronoi计算无研究的人酱油通道路过…

1:您将两个点集的数据用constant memory保存并享受constant cache加速,这个是可以的。以及,这样做容量是受到限制的,并且未必是最快的做法。

2:在点集数量较大时,您采用就地生成坐标的方法也是可以的,但是您需要权衡就地生成坐标的代价和访存的代价,选择代价较小的实现。

3:以及您为何要一定把数据放入constant memory中呢?优化访存并不只有这一种方法的。比如您完全可以将S1和S2都存放在global memory中,每线程负责一个或数个S1中的元素,每个block先整体读入S2的一部分进入shared memory——同步——比较——同步——整体将S2的下一部分读入shared memory——同步——…这样。这样可以极大地减少global memory的访存压力,同时也没有constant memory的容量限制。

大致如此,我酱油去鸟~

版主您好:
首先感谢你的回答!
我之所以想把数据放入到constant memory中,是因为我知道constant memory的访存代价比较低,这是程序优化的一个手段。对于Shared memory我不是太熟悉,请问版主,您说的那个方法有没有类似的例子可以参考一下的?
再次感谢!!!

LZ您好:

1:constant memory受益于constant cache的硬件有着很低的访存代价,以及,按照手册中的说法,需要同一warp内的线程访问constant memory中的同一个数据才能取得最好的效果。

2:我说的shared memory的用法是常规用法的,您可以参阅官方手册或者其他常见资料。

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

感覺跟Nbody Simulation很像,可參考GPU Gems 3 Chapter 31. Fast N-Body Simulation with CUDA這篇經典文章,文章中會教你怎麼去使用shared memory去prefetch data

好的,谢谢

好的,谢谢