如何在CUDA中将稀疏直方图转换为密集直方图?

时间:2013-04-12 04:23:12

标签: cuda histogram

我正在使用原始CUDA内核实现一个算法,其中每个线程块都需要该线程块的可用数据的密集直方图,现在问题是我是否必须从头开始计算密集直方图? (如果我已经有了使用共享内存实现的稀疏直方图,那么完全可以计算密集直方图)

我想出了转换的想法,我将尝试用示例详细说明我的想法(temp和hist都在共享内存中)

   0,1,2,3,4,5,6... //array indexes
   4,3,0,2,1,0,5... //contents of hist[]
   0,0,2,0,0,5,0... //contents of temp[] if(hist[x]>0)temp[x]=x;
   for_every_element     //this is sequential part :(
       if(temp[x]>0)
         shift elements from index x to 256
   4,3,2,1,0,5... //pass 1 of the for loop
   4,3,2,1,5...   //pass 2 of the for loop
                  //this goes on until all the 0s are compacted

现在我知道上面本质上是顺序的,但是可以用恒定时间(并行)完成移位,因为threads_per_block已经设置为256,所以移位不是主要问题,主要问题是如何改进这个(或欢迎任何其他建议。)

编辑:我正在考虑另一个想法,即如下 假设threads_per_block=256如果我可以计算哪个直方图箱是非零的(这个操作是并行的,因为每个线程被分配给每个bin,我可以原子地添加每个线程生成的值)让我们说我可以启动一个新的共享索引变量sindex=0,每次线程想要将值存储到d_hist[]时,它可以从sindex获取最新值并将其值存储到d_hist[sindex]=hist[treadIdx.x]之后我可以原子添加sindex

现在只有一个问题,获取sindex的值会有竞争条件,因此我可能必须设置一个标志,当一个线程向{{1添加任何值时,可以锁定或解锁该标志(但我认为这里可能存在死锁情况)

这项技术会起作用吗?还有其他比这更好的技术吗?

2 个答案:

答案 0 :(得分:1)

将稀疏直方图转换为密集直方图是一种分散操作。如果稀疏直方图由s_index[S_N]s_hist[S_N]组成,那么首先我们创建一个由全零组成的密集直方图d_hist[N](您可以从主机代码执行此操作)。然后我们用d_hist[s_index[i]] = s_hist[i];填充密集直方图。这可以并行完成并使用与稀疏直方图中的有效索引(i

对于每个线程块正在执行单独的直方图的情况可能没有意义,但您可能也对thrust scatter感兴趣。

答案 1 :(得分:0)

嗯,我想最简单的方法是找出哪个bins>0之后,并且可以完成独占扫描(为了计算目标索引,比如sum_array[]),之后为所有{ {1}}转到bins>0

d_hist[sum_array[threadIdx.x]-1]=s_hist[threadIdx.x]

我倾向于使用这种模式的原因是因为它需要log_base_2(256)时间才能计算sum_array plus,除此之外,移动和检查部件只是恒定时间操作,如果有人有不同的想法这个,请分享。