zoukankan      html  css  js  c++  java
  • MSD_radix_sort

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

    MSD的基本手法就是不断切片。
    每一步都是把整体数据切割成256片,如上图所示,实际情况切片未必均匀,有的slice内可能一个元素也没有。

    接下来对于每个切片怎么办呢?
    答案是继续切,对于特殊数据来讲,切片过程可以很快结束,这样就可以实现比LSD更快的速度。

    这里面最困难的地方就是如何存储每个slice的头和尾。
    如果采用下述方式,应该是行不通的。
    这个方式需要做数组元素插入,还要跟踪中间数据,因此没具体考虑。

    我真正采用的是下表:


    表中第一项表示第一个元素开启一个类别,紧跟的0表示此元素和上面的1是同一类。
    至于2表明在切片过程中是一个孤立的元素,后续就没必要再切片了。
    这个方式可以大大简化编码。

    二、伪代码。

    for each slice
        if slice-tag == 2 continue;
        if slice-tag == 1
            slice it;
            update bookkeeping
    int main(){
        HANDLE heap = NULL;
        Bucket bucket[BUCKETSLOTCOUNT];
        PageList * pageListPool;
        int plpAvailable = 0;
        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, 1024*1024, 0);
        if (heap != NULL){
            pages = (int * )HeapAlloc(heap, 0, (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + 8) * PAGEAMOUNT);
            pageListPool = (PageList *)HeapAlloc(heap, 0, (TFSI/PAGEGRANULAR + 8) * sizeof(PageList));
            s = (unsigned short *)HeapAlloc(heap, 0, TFSI*sizeof(unsigned short));
            objIdx = (int *)HeapAlloc(heap, 0, TFSI * sizeof(int));
            classifier = (__int8 *)HeapAlloc(heap, 0, (TFSI+8)*sizeof(__int8));
        }
        MakeSure(pages != NULL && pageListPool != NULL && objIdx != NULL && classifier != NULL);
    
        for(int i=0; i<TFSI; i++) objIdx[i]=i;
        timeBegin = clock();
        for (int i=0; i<TFSI; i++) s[i] = rand();
        timeEnd = clock();
        printf("
    %f(s) consumed in generating numbers", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC);
    
        SecureZeroMemory(classifier, TFSI*sizeof(__int8));
        classifier[0] = 1;
        classifier[TFSI] = 1;
        
        timeBegin = clock();
    
        bool no_need_further_processing = false;
        for (int t=sizeof(short)-1; t>=0; t--){
            int bucketIdx;
            int slice_pointer = 0;
            int slice_base = 0;
            int flagCounter = 0;
    
            if (no_need_further_processing) break;
    
            //classifier: 1 new catagory
            //classifier: 2 completed catagory process
            while (slice_pointer < TFSI){
                if (classifier[slice_pointer] == 2){
                    slice_base = slice_pointer;
                    classifier[slice_base] = 0;
                    while (classifier[slice_pointer] == 0){
                        slice_pointer++;
                        flagCounter++;
                    }
                    classifier[slice_base] = 2;
    
                    if (flagCounter == TFSI) no_need_further_processing = true;
                    continue;
                }
                
                if (classifier[slice_pointer] == 1){
                    FillMemory(pages, (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + 8) * PAGEAMOUNT, 0xff);
                    SecureZeroMemory(pageListPool, (TFSI/PAGEGRANULAR + 8) * sizeof(PageList));
                    pagesAvailable = pages;
                    plpAvailable = 0;
    
                    for(int i=0; i<256; i++){
                        bucket[i].currentPagePtr = pagesAvailable;
                        bucket[i].offset = 0;
                        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] = 0;
                    while (classifier[slice_pointer] == 0){
                        //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 = 0;
                            pagesAvailable += PAGEGRANULAR;
                            
                            bucket[bucketIdx].currentPageListItem = bucket[bucketIdx].currentPageListItem->next;
                        }
    
                        slice_pointer++;
                    }
                    classifier[slice_base] = 1;
    
                    //update classifier;
                    //update objIdx index
                    int start = slice_base;
                    for (int i=0; i<256; i++){
                        PageList * p;
                        p = &(bucket[i].pl);
                        //classifier: 1 new catagory
                        //classifier: 2 complete catagory process
                        classifier[start] = 1;
    
                        int counters = 0;
                        while (p){
                            for (int t=0; 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 == 1) classifier[start-1] = 2;
                    }
                    //update objIdx index
                }   //if (classifier[slice_pointer] == 1)
            }        //while (slice_pointer < TFSI) 
        }            //for (int t=sizeof(short)-1; t>=0; t--)
    
        timeEnd = clock();
        printf("
    %f(s) consumed in generating results", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC);
        
        //for(int i=0; i<TFSI; i++) printf("%d
    ", s[objIdx[i]]);
    
        HeapFree(heap, 0, pages);
        HeapFree(heap, 0, pageListPool);
        HeapFree(heap, 0, s);
        HeapFree(heap, 0, objIdx);
        HeapFree(heap, 0, classifier);
        HeapDestroy(heap);
    
        return 0;
    }

    三、测试

    1024*1024*100 个短整型。

    时间  5.438s

    看到这里就知道杯具了,比LSD还慢。

    如果应用到二维表,会更惨不忍睹。试了下果然如此。

    四、讨论

    如果哪位有更好的方法,欢迎讨论。

    或者,基数排序只是一个花瓶?

  • 相关阅读:
    3.1 history跳转页面产生跨域问题
    2021年6月7日 团队冲刺第二阶段04
    2021年6月6日 团队冲刺第二阶段03
    2021年6月5日 团队冲刺第二阶段02
    2021年6月4日 团队冲刺第二阶段01
    2021年6月3日
    2021年6月2日
    2021年6月1日
    2021年5月31日
    2021年5月30日
  • 原文地址:https://www.cnblogs.com/servo/p/3371038.html
Copyright © 2011-2022 走看看