陣列,map,unordered_map的簡單效能測試

lt發表於2016-10-18

用c++來實現類似資料庫中的分組操作。現在把從1~1千萬的數,按照分別取3、5、7的模來分組,計算各分組的數字個數和數字總和。

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#include <vector>
#include <algorithm>
#include <map>
#include <unordered_map>


int test0()
{
    static int cnt[700];
    static long long sum[700];
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    key=i%3+(i%5)*10+(i%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}


int test1()
{
    static std::unordered_map<int, int> cnt;
    static std::unordered_map<int, long long> sum;
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    key=i%3+(i%5)*10+(i%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}

int test2()
{
    static std::map<int, int> cnt;
    static std::map<int, long long> sum;
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    key=i%3+(i%5)*10+(i%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}

int main()
{
    long a;

    a=clock();
    test0();
    printf("%dms\n",clock()-a);

    a=clock();
    test1();
    printf("%dms\n",clock()-a);

    a=clock();
    test2();
    printf("%dms\n",clock()-a);

    return 0;
} 

在筆記本上的vc2015上編譯及執行結果。

D:\>cl cube.cpp /EHsc /O2
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.20506.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

cube.cpp
Microsoft (R) Incremental Linker Version 10.00.20506.01
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:cube.exe
cube.obj

D:\>timer cube
Timer 9.01 : Igor Pavlov : Public domain : 2009-05-31
240,95239,476195380956
93ms
240,95239,476195380956
1623ms
240,95239,476195380956
751ms

Kernel Time  =     0.015 =    0%
User Time    =     2.449 =   95%
Process Time =     2.464 =   96%
Global Time  =     2.552 =  100%

按理說,用hash實現的unordered_map效能應該比二叉樹的map高,結果卻不是。 由於我的筆記本上沒裝gcc,所以在一臺驍龍615手機上用c4droid 4.96(gcc 6.2)編譯執行結果。 enter image description here

很奇怪,map和unordered_map的效能出現了反轉,是否微軟的unordered_map實現不太好呢,我記得vc6/2002的hash_map效能就比sgi stl的差。沒想到這麼多年了,還是這樣。

考慮到二叉樹的插入和新增的值順序有關,故意打亂順序,這次vc2015和gcc的結果比例一致了。

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 

#include <vector>
#include <algorithm>
#include <map>
#include <unordered_map>
int b[100000000];
int shuf(int a[],int b)
{
    for(int i=0;i<b;i++)
    {
        a[i]=i;
    }
    for(int i=b;i>0;)
    {
        int t=rand()%b;
        i--;
        int temp=a[i];
        a[i]=a[t];
        a[t]=temp;
    }
    return 0;
}

int test0()
{
    static int cnt[700];
    static long long sum[700];
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    int j=b[i];
    key=j%3+(j%5)*10+(j%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}


int test1()
{
    static std::unordered_map<int, int> cnt;
    static std::unordered_map<int, long long> sum;
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    int j=b[i];
    key=j%3+(j%5)*10+(j%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}

int test2()
{
    static std::map<int, int> cnt;
    static std::map<int, long long> sum;
    int key=0;

    for(int i=0;i<10000000;i++)
    {
    int j=b[i];
    key=j%3+(j%5)*10+(j%7)*100;
    cnt[key]++;
    sum[key]+=i;
    }

    printf("%d,%d,%lld\n",key,cnt[key],sum[key]);
    return 0;
}

int main()
{
    long a;
    shuf(b,10000000);

    a=clock();
    test0();
    printf("%dms\n",clock()-a);

    a=clock();
    test1();
    printf("%dms\n",clock()-a);

    a=clock();
    test2();
    printf("%dms\n",clock()-a);

    return 0;
} 

測試結果:

D:\>cl cube2.cpp /EHsc /O2 -o cube2153.exe
用於 x86 的 Microsoft (R) C/C++ 優化編譯器 19.00.24215.1 版
版權所有(C) Microsoft Corporation。保留所有權利。

cl: 命令列 warning D9035 :“o”選項已否決,並將在將來的版本中移除
cube2.cpp
Microsoft (R) Incremental Linker Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:cube2.exe
/out:cube2153.exe
cube2.obj

D:\>cube2153
612,95238,476199355688
48ms
612,95238,476199355688
201ms
612,95238,476199355688
714ms

D:\>g++ cube2.cpp -o cube2gcc.exe -O2

D:\>cube2gcc
612,95238,476199355688
63ms
612,95238,476199355688
339ms
612,95238,476199355688
533ms

相關文章