MSD_radix_sort
一、这次是在上一次尝试基础上进行的,预期是达到上次性能的9倍。

MSD的基本手法就是不断切片。
每一步都是把整体数据切割成256片,如上图所示,实际情况切片未必均匀,有的slice内可能一个元素也没有。
接下来对于每个切片怎么办呢?
答案是继续切,对于特殊数据来讲,切片过程可以很快结束,这样就可以实现比LSD更快的速度。
这里面最困难的地方就是如何存储每个slice的头和尾。
如果采用下述方式,应该是行不通的。
这个方式需要做数组元素插入,还要跟踪中间数据,因此没具体考虑。
我真正采用的是下表:

表中第一项表示第一个元素开启一个类别,紧跟的0表示此元素和上面的1是同一类。
至于2表明在切片过程中是一个孤立的元素,后续就没必要再切片了。
这个方式可以大大简化编码。
二、伪代码。
for each slice
if slice-tag == continue;
if slice-tag ==
slice it;
update bookkeeping
int main(){
HANDLE heap = NULL;
Bucket bucket[BUCKETSLOTCOUNT];
PageList * pageListPool;
int plpAvailable = ;
int * pages = NULL;
int * pagesAvailable = NULL;
int * objIdx;
unsigned short * s;
__int8 * classifier = NULL;
time_t timeBegin;
time_t timeEnd;
heap = HeapCreate(HEAP_NO_SERIALIZE|HEAP_GENERATE_EXCEPTIONS, *, );
if (heap != NULL){
pages = (int * )HeapAlloc(heap, , (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + ) * PAGEAMOUNT);
pageListPool = (PageList *)HeapAlloc(heap, , (TFSI/PAGEGRANULAR + ) * sizeof(PageList));
s = (unsigned short *)HeapAlloc(heap, , TFSI*sizeof(unsigned short));
objIdx = (int *)HeapAlloc(heap, , TFSI * sizeof(int));
classifier = (__int8 *)HeapAlloc(heap, , (TFSI+)*sizeof(__int8));
}
MakeSure(pages != NULL && pageListPool != NULL && objIdx != NULL && classifier != NULL);
for(int i=; i<TFSI; i++) objIdx[i]=i;
timeBegin = clock();
for (int i=; i<TFSI; i++) s[i] = rand();
timeEnd = clock();
printf("\n%f(s) consumed in generating numbers", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC);
SecureZeroMemory(classifier, TFSI*sizeof(__int8));
classifier[] = ;
classifier[TFSI] = ;
timeBegin = clock();
bool no_need_further_processing = false;
for (int t=sizeof(short)-; t>=; t--){
int bucketIdx;
int slice_pointer = ;
int slice_base = ;
int flagCounter = ;
if (no_need_further_processing) break;
//classifier: 1 new catagory
//classifier: 2 completed catagory process
while (slice_pointer < TFSI){
if (classifier[slice_pointer] == ){
slice_base = slice_pointer;
classifier[slice_base] = ;
while (classifier[slice_pointer] == ){
slice_pointer++;
flagCounter++;
}
classifier[slice_base] = ;
if (flagCounter == TFSI) no_need_further_processing = true;
continue;
}
if (classifier[slice_pointer] == ){
FillMemory(pages, (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + ) * PAGEAMOUNT, 0xff);
SecureZeroMemory(pageListPool, (TFSI/PAGEGRANULAR + ) * sizeof(PageList));
pagesAvailable = pages;
plpAvailable = ;
for(int i=; i<; i++){
bucket[i].currentPagePtr = pagesAvailable;
bucket[i].offset = ;
bucket[i].pl.PagePtr = pagesAvailable;
bucket[i].pl.next = NULL;
pagesAvailable += PAGEGRANULAR;
bucket[i].currentPageListItem = &(bucket[i].pl);
}
slice_base = slice_pointer;
classifier[slice_base] = ;
while (classifier[slice_pointer] == ){
//for each slice element, push_back to pages;
unsigned char * cell = (unsigned char *)&s[objIdx[slice_pointer]];
bucketIdx = cell[t];
//save(bucketIdx, objIdx[i]);
bucket[bucketIdx].currentPagePtr[ bucket[bucketIdx].offset ] = objIdx[slice_pointer];
bucket[bucketIdx].offset++;
if (bucket[bucketIdx].offset == PAGEGRANULAR){
bucket[bucketIdx].currentPageListItem->next = &pageListPool[plpAvailable];
plpAvailable++;
bucket[bucketIdx].currentPageListItem->next->PagePtr = pagesAvailable;
bucket[bucketIdx].currentPageListItem->next->next = NULL;
bucket[bucketIdx].currentPagePtr = pagesAvailable;
bucket[bucketIdx].offset = ;
pagesAvailable += PAGEGRANULAR;
bucket[bucketIdx].currentPageListItem = bucket[bucketIdx].currentPageListItem->next;
}
slice_pointer++;
}
classifier[slice_base] = ;
//update classifier;
//update objIdx index
int start = slice_base;
for (int i=; i<; i++){
PageList * p;
p = &(bucket[i].pl);
//classifier: 1 new catagory
//classifier: 2 complete catagory process
classifier[start] = ;
int counters = ;
while (p){
for (int t=; t<PAGEGRANULAR; t++){
int idx = p->PagePtr[t];
if (idx != TERMINATOR){
objIdx[start] = idx;
start++;
counters++;
}
if (idx == TERMINATOR) break;
}
p = p->next;
}
if (counters == ) classifier[start-] = ;
}
//update objIdx index
} //if (classifier[slice_pointer] == 1)
} //while (slice_pointer < TFSI)
} //for (int t=sizeof(short)-1; t>=0; t--)
timeEnd = clock();
printf("\n%f(s) consumed in generating results", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC);
//for(int i=0; i<TFSI; i++) printf("%d\n", s[objIdx[i]]);
HeapFree(heap, , pages);
HeapFree(heap, , pageListPool);
HeapFree(heap, , s);
HeapFree(heap, , objIdx);
HeapFree(heap, , classifier);
HeapDestroy(heap);
return ;
}
三、测试
1024*1024*100 个短整型。
时间 5.438s
看到这里就知道杯具了,比LSD还慢。
如果应用到二维表,会更惨不忍睹。试了下果然如此。
四、讨论
如果哪位有更好的方法,欢迎讨论。
或者,基数排序只是一个花瓶?
MSD_radix_sort的更多相关文章
- 读写ini文件
C# 使用文件流来读写ini文件 背景 之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便.然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI ...
随机推荐
- Install ElasticSearch plugin for head
git clone git://github.com/mobz/elasticsearch-head.git yum install git npm cd elasticsearch-head npm ...
- php数组·的方法-数组检索
/* * //数组检索函数 * */ //array_keys() 获取数组中所有键名 //array_values() 获取数组中所有键名 $arr6=range('a','e'); print_r ...
- py---------常用模块2
一.hashilb 模块 python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固 ...
- Apache重定向URL
(1)去除httpd.conf文件中"#LoadModule rewrite_module modules/mod_rewrite.so"前面的"#"号; (2 ...
- 获取tomcat路径
String serverPath = System.getProperty("catalina.home");
- git使用笔记-提高篇-重置揭密
https://git-scm.com/book/zh/v2/Git-%E5%B7%A5%E5%85%B7-%E9%87%8D%E7%BD%AE%E6%8F%AD%E5%AF%86 重置揭密 在继续了 ...
- Java基础12-数组求最大值以及排序
1.求最大值 实例:小明买手机,询问了4家店的价格,分别是2800,2900,2600,3000,输出最低价 正确代码:类似打擂台,将数组第一个值赋给最小值,然后依次比较 import java.ut ...
- Cinder Columns
http://www.screencast.com/users/xiangxinyong/folders/Smaug http://www.screencast.com/t/SLqCyOwtBRl
- Spring Aware
spring依赖注入的最大亮点就是所有的bean感知不到spring容器的存在,但在实际开发中,我们不可避免的要用到spring容器本身的功能资源,这时,我们就必须意识到容器的存在(废话,都要跟容器进 ...
- DedeCMS {dede:field name='array' /}的用法
field支持用array获取任意字段的值.(支持标记:文章列表模板的 {dede:field name='array' /}.arclist.arclistsg.loop.sql 标签) 例如平 ...