您的位置:首页 > 运维架构

AMD OpenCL例子阅读笔记系列之Radix_Sort(一)

2014-05-13 15:24 399 查看
      又是好久没来了,这次我们来看看Radix_Sort也就是基数排序。为了更好地理解,这里先贴一个网上的基数排序的博文:

      http://www.cnblogs.com/Braveliu/archive/2013/01/21/2870201.html
      再贴上百度上的一些介绍性的内容:

     (radix sort)则是属于“分配式排序”(distribution sort),基数排序法又称“桶子法”(bucket
sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O
(nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。

    先来看下RadixSort.cpp中的主机端参考代码:

int
RadixSort::hostRadixSort()
{
cl_uint *histogram = (cl_uint*)malloc(RADICES * sizeof(cl_uint));
CHECK_ALLOCATION(histogram, "Failed to allocate host memory. (histogram)");

cl_uint *tempData = (cl_uint*)malloc(elementCount * sizeof(cl_uint));
CHECK_ALLOCATION(tempData, "Failed to allocate host memory. (tempData)");

if(histogram != NULL && tempData != NULL)
{
memcpy(tempData, unsortedData, elementCount * sizeof(cl_uint));
for(int bits = 0; bits < sizeof(cl_uint) * RADIX ; bits += RADIX)
{
// Initialize histogram bucket to zeros
//分配256个元素大小的空间到histogram
memset(histogram, 0, RADICES * sizeof(cl_uint));

// Calculate 256 histogram for all element
for(int i = 0; i < elementCount; ++i)
{
cl_uint element = tempData[i];
//获取后面8位的数据
cl_uint value = (element >> bits) & RADIX_MASK;
//就是传说中的histogram柱状图累加,实际就是记录索引量下面的
//数据个数
histogram[value]++;
}

// Prescan the histogram bucket
//求取第i个桶的边界信息(为左边界值)
//注意这里的处理方式与文中的区别
cl_uint sum = 0;
for(int i = 0; i < RADICES; ++i)
{
cl_uint val = histogram[i];
histogram[i] = sum;
sum += val;
}

// Rearrange  the elements based on prescaned histogram
//在获得边界值后进行排序
for(int i = 0; i < elementCount; ++i)
{
cl_uint element = tempData[i];
cl_uint value = (element >> bits) & RADIX_MASK;
//获取key值在桶中的索引
cl_uint index = histogram[value];
//根据在桶中的索引值将其安排在已排序数组中的对应位置
//实际就是将数据放到桶里,只不过这里一步完成了scatter gather两个工作
hSortedData[index] = tempData[i];
//将索引位置后移一位
histogram[value] = index + 1;
}

// Copy to tempData for further use
//这个很容易理解,因为第三次之后直接将结果存在hSortedData中了,没有必要再次复制
if(bits != RADIX * 3)
{
memcpy(tempData, hSortedData, elementCount * sizeof(cl_uint));
}
}
}

FREE(tempData);
FREE(histogram);
return SDK_SUCCESS;
}

       上面我已经做了一些注释,与推荐参考的博文略有区别的只是索引位置的处理上,一个是取的桶的右边界,一个取的是桶的左边界。但是我感觉上面代码的这种方式更有亲和力。O(∩_∩)O~

       基数排序这个例子比较庞大,打算分开来写。这里先写一下主机实现部分。另外对于环境的构建如平台选择、设备选择等将略过不谈,下一讲将讲解RadixSort的并行思想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  opencl 算法