一、这次是在上一次尝试基础上进行的,预期是达到上次性能的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的更多相关文章

  1. 读写ini文件

    C# 使用文件流来读写ini文件 背景 之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便.然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI ...

随机推荐

  1. Oracle外连接与条件的组合

    由于很少使用SQL 92语法,今天写个outer join的时候被搞晕了.参考了一些例子后整理如下.总结,"inter join on"中的条件是对table进行joining的r ...

  2. hdu1686 KMP 求在字符串A中字符串B出现的次数

    Oulipo Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  3. pm2 启动后台 node js

    1,安装node js 参看:https://www.cnblogs.com/wf-l5201314/p/9229974.html 2,pm2安装(安装环境linux / os) 命令:npm ins ...

  4. 原生JS实现图片拖拽移动与缩放

    看一下最终效果,图片可以拖动,可以缩放 把代码贴出来,可以直接粘贴使用,大致的思想就是鼠标按下的时候获取当时的鼠标位置,要减去left和top值,移动的时候获取位置减去初始的值就得到移动的时候的lef ...

  5. hadoop install start-dfs.sh 失败

    linux:ubuntu 16.04 LTS hadoop version: 2.7.3 JDK: java-9-open-jdk issue: start-dfs.sh start-dfs.sh:c ...

  6. java多线程(四)

    一个例子: Account.java 客户实体类 package com.asiainfo.test.thread8; /** * 账户类 * @author luke * */ public cla ...

  7. 使用WindowsAPI播放PCM音频

    这一篇文章同上一篇<使用WindowsAPI获取录音音频>原理具有相似之处,不再详细介绍函数与结构体的参数 1. waveOutGetNumDevs 2. waveOutGetDevCap ...

  8. ubuntu使用ppa源安装最新版本的git

    国内也有ubuntu镜像源.但是里面的git都是1.9版本.最新的已经是2.3了 1 首先使用将ppa源加入Ubuntu,交大家 sudo add-apt-repository ppa:pdoes/p ...

  9. C语言答案解析

    1.设整型变量 a=2,则执行下列语句后,浮点型变量b的值不为0.5的是(  B ) A) b=1.0/a            B) b=(float)(1/a) C) b=1/(float)a   ...

  10. Java学习笔记--继承和多态(中)

    1.通过继承来开发超类(superclass) 2.使用super 关键词唤起超类的构造方法 3.在超类中覆盖方法 4.区分override和overload 5.在Object类中探索toStrin ...