Cuda 具有散乱线段的分段约简

Cuda 具有散乱线段的分段约简,cuda,opencl,gpgpu,reduction,Cuda,Opencl,Gpgpu,Reduction,我需要在GPU上解决一个相当标准的问题,但我对实用的GPGPU还很陌生,所以我正在寻找解决这个问题的方法 我在3-空间中有许多点被分配到一个非常小的组(每个点属于一个组),在这种情况下,特别是15个(永远不会改变)。现在我想计算所有组的均值和协方差矩阵。因此,在CPU上,它大致与: for each point p { mean[p.group] += p.pos; covariance[p.group] += p.pos * p.pos; ++count[p.group

我需要在GPU上解决一个相当标准的问题,但我对实用的GPGPU还很陌生,所以我正在寻找解决这个问题的方法

我在3-空间中有许多点被分配到一个非常小的组(每个点属于一个组),在这种情况下,特别是15个(永远不会改变)。现在我想计算所有组的均值和协方差矩阵。因此,在CPU上,它大致与:

for each point p
{
    mean[p.group] += p.pos;
    covariance[p.group] += p.pos * p.pos;
    ++count[p.group];
}

for each group g
{
    mean[g] /= count[g];
    covariance[g] = covariance[g]/count[g] - mean[g]*mean[g];
}
由于组的数量非常少,最后一步可以在CPU上完成(无论如何,我需要CPU上的那些值)。第一步实际上只是一个分段的减少,但是分段分散在周围

所以我想到的第一个想法是,首先按照他们的分组对点进行排序。我考虑过使用
atomic_inc
进行简单的桶排序,以计算桶大小和每点重定位指数(有更好的排序方法吗?原子可能不是最好的方法)。在这之后,他们被分组排序,我可能会提出一个分段扫描算法的自适应方案

但在这种特殊情况下,我在每个点上获得了大量的数据(9-10个浮点,如果需要,甚至可以加倍),因此使用每个线程共享内存元素和每个点线程的标准算法可能会在将每个多处理器资源视为共享内存或寄存器方面出现问题(好的,1.x版的计算能力比2.x版的要多,但仍然如此)

由于小组数量非常少且恒定,我认为可能会有更好的方法。可能已经有适合此类标准问题的特定属性的现有想法。或者可能我的一般方法没有那么糟糕,您有改进单个步骤的想法,比如适合于非常复杂问题的良好排序算法少量密钥或某些分段缩减算法,最大限度地减少共享内存/寄存器的使用


我正在寻找通用的方法,不想使用外部库。FWIW我正在使用OpenCL,但这并不重要,因为GPU计算的一般概念在主要的框架中并没有真正的区别。

即使只有很少的组,我不认为您将能够避免在保持ping降低步骤的效率。您可能还希望执行完整排序,而不仅仅是索引排序,因为这将有助于在降低步骤中保持内存访问效率

要进行排序,请阅读此处的一般策略:

对于减少(旧但仍然良好):

对于并行缩减的示例实现:


这是一种非常常见的模式。使用推力,您首先要
按键排序
将每个段中的数据汇集在一起,然后
按键减少
计算每个组的平均值和协方差。