我真的很喜欢编程和Cuda很抱歉,如果这是非常明显的.基本上我有一个C函数,它读取数据列表,然后根据hashmap检查每个项目(我在C中使用uthash).它运行良好,但我想在Cuda中运行这个过程(一旦它获得了散列键的值,那么它会进行很多处理),但我不确定创建尽可能快的只读散列函数的最佳方法在库达.
背景:
基本上我试图尽快评估一大批投资组合.我不断得到数百万个投资组合,这些投资组合是两个列表.一个有股票名称,另一个有权重.然后,我使用股票名称查找哈希表以获取其他数据(值,%更改等),然后根据权重处理它.在普通C的CPU上大约需要8分钟,所以我很有兴趣在GPU上尝试它.我已经阅读并完成了这些示例,cuda by example所以我相信我知道如何除了散列函数之外大部分都是这样做的(附录中有一个但是它似乎集中在添加它,而我真的只想要它作为参考,因为它'永远不会改变.我可能会在边缘粗糙,cuda for example所以在这种情况下,我可能会遗漏一些对我有帮助的东西,比如使用文本或某种特殊形式的记忆.如果每个块都有自己对hashmap的访问权限,或者每个线程是否足以满足整个GPU的要求,我将如何构建此结果以获得最佳结果?
任何想要更好地理解这一点的想法,例子或资源都会很棒.
谢谢!
编辑:很抱歉只是为了澄清,我只使用C.最糟糕的情况我愿意使用另一种语言,但理想情况下我想要一些我可以原生地放在GPU上的东西,并且从那以后所有未来的线程都被读取为了处理我的数据,我需要在几个大批量中进行处理.
这是关于在GPU上使用哈希映射的潜在性能问题的一些想法,以备份关于将哈希映射保留在CPU上的注释.
NVIDIA GPU以32个线程为一组运行线程,称为warp.为了获得良好的性能,warp中的每个线程必须基本上做同样的事情.也就是说,它们必须运行相同的指令,并且必须从彼此接近的存储器位置读取.
我认为哈希映射可能会破坏这两个规则,可能会使GPU降低太多,以至于无法在GPU上保留哈希映射.
考虑一下warp运行中的32个线程会发生什么:
首先,每个线程都必须创建股票名称的哈希值.如果这些名称的长度不同,则对于不同的长度,这将涉及散列循环中的不同轮数,并且warp中的所有线程必须等待完成最长名称的散列.根据散列算法,代码可以在散列算法中采用不同的路径.每当warp中的不同线程需要采用不同的路径时,相同的代码必须运行多次(每个代码路径一次).这称为经线发散.
当warp中的所有线程都获得了一个哈希时,每个线程必须从慢速全局内存中的不同位置读取(由哈希指定).当经线中的32个线程中的每个线程以紧密,连贯的模式读取时,GPU以最佳方式运行.但现在,每个线程都从内存中基本上随机的位置读取.这可能导致GPU必须序列化所有线程,可能会将性能降低到潜在的1/32.
线程读取的内存位置是散列桶.每个可能包含不同数量的哈希值,再次导致warp中的线程必须执行不同的操作.然后,他们可能必须再次分支,每个分支到一个随机位置,以获得映射的实际结构.
如果您将库存名称和数据结构保存在CPU上的哈希映射中,则可以使用CPU将存储在GPU擅长处理的精确模式中的信息数组放在一起.根据CPU的繁忙程度,您可以在GPU处理先前提交的工作时执行此操作.
这也使您有机会将CPU上的结构数组(AoS)更改为GPU的数组结构(SoA).如果你不熟悉这个概念,基本上,你转换:
my_struct {
int a;
int b;
};
my_struct my_array_of_structs[1000];
Run Code Online (Sandbox Code Playgroud)
至:
struct my_struct {
int a[1000];
int b[1000];
} my_struct_of_arrays;
Run Code Online (Sandbox Code Playgroud)
这使得所有的a彼此相邻在内存中,这样当warp中的32个线程到达读取的指令时a,所有的值都整齐地排列在一起,导致整个warp能够加载价值很快.b当然,情况也是如此.