0

理論的には、ダブル ワードの加算/減算のコストは、シングル ワードの 2 倍になります。同様に、1 ワードの乗算と加算のコスト比は 3 とします。Ubuntu LTS 14.04 で GCC を使用して次の C プログラムを作成し、Intel Sandy Bridge Corei5-2410M マシンのクロック サイクル数をチェックしました。ただし、ほとんどの場合、プログラムは 128 ビットの加算に対して 6 クロック サイクルを返しますが、私は最良のケースを取り上げました。コマンド (gcc -o ow -O3 cost.c) を使用してコンパイルした結果を以下に示します。

32-bit Add: Clock cycles = 1    64-bit Add: Clock cycles = 1    64-bit Mult: Clock cycles = 2   128-bit Add: Clock cycles = 5 

プログラムは次のとおりです。

#define n 500
#define counter 50000

typedef uint64_t utype64;
typedef int64_t type64;
typedef __int128 type128;

__inline__ utype64 rdtsc() {
        uint32_t lo, hi;
        __asm__ __volatile__ ("xorl %%eax,%%eax \n        cpuid"::: "%rax", "%rbx", "%rcx", "%rdx");
        __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
        return (utype64)hi << 32 | lo;
}

int main(){
    utype64 start, end;
    type64 a[n], b[n], c[n];
    type128 d[n], e[n], f[n];
    int g[n], h[n];
    unsigned short i, j;
    srand(time(NULL));
    for(i=0;i<n;i++){ g[i]=rand(); h[i]=rand(); b[i]=(rand()+2294967295); e[i]=(type128)(rand()+2294967295)*(rand()+2294967295);}
    for(j=0;j<counter;j++){
       start=rdtsc();
       for(i=0;i<n;i++){ a[i]=(type64)g[i]+h[i]; }
       end=rdtsc();
       if((j+1)%5000 == 0)
          printf("%lu-bit Add: Clock cycles = %lu \t", sizeof(g[0])*8, (end-start)/n);

       start=rdtsc();
       for(i=0;i<n;i++){ c[i]=a[i]+b[i]; }
       end=rdtsc();
       if((j+1)%5000 == 0)
          printf("%lu-bit Add: Clock cycles = %lu \t", sizeof(a[0])*8, (end-start)/n);

       start=rdtsc();
       for(i=0;i<n;i++){ d[i]=(type128)c[i]*b[i]; }
       end=rdtsc();
       if((j+1)%5000 == 0)
          printf("%lu-bit Mult: Clock cycles = %lu \t", sizeof(c[0])*8, (end-start)/n);

       start=rdtsc();
       for(i=0;i<n;i++){ f[i]=d[i]+e[i]; }
       end=rdtsc();
       if((j+1)%5000 == 0){
          printf("%lu-bit Add: Clock cycles = %lu \n", sizeof(d[0])*8, (end-start)/n);
        printf("f[%hu]= %ld %ld \n\n", i-7, (type64)(f[i-7]>>64), (type64)(f[i-7]));}
   }

return 0;
}

この結果で気になる点が2つあります。

1) (64 ビット) 乗算のクロック サイクル数は 2 にできますか?

2) ダブルワード加算のクロックサイクル数がシングルワード加算の 2 倍以上なのはなぜですか?

主に(2)のケースが気になります。ここで、私のプログラム ロジックが原因なのかという疑問が生じます。それともGCCコンパイラの最適化によるものですか?

4

1 に答える 1