ホーム 道しるべ 憩いの広場 濃緑空間 濃緑研の日記

x86FPUとの比較
ホーム ] 上へ ] 普通に時間測定 ] ループ展開・時間測定 ] ペアリング最適化I ] ペアリング最適化II ] [ x86FPUとの比較 ] 3DNow!SISDと比較 ] 配列演算総括 ]

 

まずは、C言語でのコンパイラコードで比較してみましょう。
PentiumIIor!!!とか他のx86互換CPUでの実行結果を見てみるのもおもしろいでしょう。

#include "amd3d.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>

mtrx(float a[4], float b[4][4], float c[4])
{
        c[0] = a[0]*b[0][0] + a[1]*b[0][1] + a[2]*b[0][2] + a[3]*b[0][3];
        c[1] = a[0]*b[1][0] + a[1]*b[1][1] + a[2]*b[1][2] + a[3]*b[1][3];
        c[2] = a[0]*b[2][0] + a[1]*b[2][1] + a[2]*b[2][2] + a[3]*b[2][3];
        c[3] = a[0]*b[3][0] + a[1]*b[3][1] + a[2]*b[3][2] + a[3]*b[3][3];
}

main()
{
    float    a[4]={0,1,1,0};
    float     b[4][4]={{1,0,0,0},{0,0,1,0},{0,-1,0,0},{0,0,0,1}};
    float    c[4];
    char    buf[80];

long    n;
    DWORD    dt1,dt2;
    double    ddt;
   
    dt1 = GetTickCount();

    for(n=0;n<100000000;n++)
    {
        mtrx(a,b,c);
    }

    dt2 = GetTickCount();
    ddt = (double)(dt2-dt1)/1000.0;
    sprintf(buf,"%f %f %f %f\nFPUによる処理時間は %.3f 秒です",c[0],c[1],c[2],c[3],ddt);
    MessageBox(GetDesktopWindow(), buf,"Test 3DNow!",MB_OK);
}

次にmtrxを以下のアセンブラコードに置き換えてみましょう。

mtrx(float a[4], float b[4][4], float c[4])
{
    _asm{
        mov         edi,a             // edi = 配列a[0]のアドレス
        mov         ebx,b             // ebx = 配列b[0][0]のアドレス
        mov         ecx,c             // ecx = 配列c[0]のアドレス

        fld         [edi]             // a[0]
        fld         [edi+4]             // a[1] a[0]
        fld         [edi+8]             // a[2] a[1] a[0]
        fld         [edi+12]         // a[3] a[2] a[1] a[0]
        fld         [ebx]             // b[0][0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+4]             // b[0][1] b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[0][1]*a[1] b[0][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+8]             // b[0][2] b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(3)         // b[0][2]*a[2] b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[0][2]*a[2]+b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+12]         // b[0][3] b[0][2]*a[2]+b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(2)         // b[0][3]*a[3] b[0][2]*a[2]+b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[0][3]*a[3]+b[0][2]*a[2]+b[0][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fstp    [ecx]             // c[0] = b[0][3]*a[3]+b[0][2]*a[2]+b[0][1]*a[1]+b[0][0]*a[0]
                                // a[3] a[2] a[1] a[0]
        fld         [ebx+16]         // b[1][0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+20]         // b[1][1] b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[1][1]*a[1] b[1][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+24]         // b[1][2] b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(3)         // b[1][2]*a[2] b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[1][2]*a[2]+b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+28]         // b[1][3] b[1][2]*a[2]+b[1][1]*a[1]+b[0][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(2)         // b[1][3]*a[3] b[1][2]*a[2]+b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[1][3]*a[3]+b[1][2]*a[2]+b[1][1]*a[1]+b[1][0]*a[0] a[3] a[2] a[1] a[0]
        fstp    [ecx+4]             // c[1] = b[1][3]*a[3]+b[1][2]*a[2]+b[1][1]*a[1]+b[1][0]*a[0]
                                // a[3] a[2] a[1] a[0]
        fld         [ebx+32]         // b[2][0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+36]         // b[2][1] b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(4)         // b[2][1]*a[1] b[2][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+40]         // b[2][2] b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(3)         // b[2][2]*a[2] b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[2][2]*a[2]+b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fld         [ebx+44]         // b[2][3] b[2][2]*a[2]+b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fmul    ST,ST(2)         // b[2][3]*a[3] b[2][2]*a[2]+b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        faddp    ST(1),ST         // b[2][3]*a[3]+b[2][2]*a[2]+b[2][1]*a[1]+b[2][0]*a[0] a[3] a[2] a[1] a[0]
        fstp    [ecx+8]             // c[2] = b[2][3]*a[3]+b[2][2]*a[2]+b[2][1]*a[1]+b[2][0]*a[0]
                                // a[3] a[2] a[1] a[0]
        fld         [ebx+48]         // b[3][0] a[3] a[2] a[1] a[0]
        fmulp    ST(4),ST         // a[3] a[2] a[1] b[3][0]*a[0]
        fld         [ebx+52]         // b[3][1] a[3] a[2] a[1] b[3][0]*a[0]
        fmulp    ST(3),ST         // a[3] a[2] a[1]+b[3][1] b[3][0]*a[0]
        fld         [ebx+56]         // b[3][2] a[3] a[2] a[1]*b[3][1] b[3][0]*a[0]
        fmulp    ST(2),ST         // a[3] a[2]*b[3][2] a[1]*b[3][1] b[3][0]*a[0]
        fld         [ebx+60]         // b[3][3] a[3] a[2]*b[3][2] a[1]*b[3][1] b[3][0]*a[0]
        fmulp    ST(1),ST         // b[3][3]*a[3] a[2]*b[3][2] a[1]*b[3][1] b[3][0]*a[0]
        faddp    ST(1),ST         // b[3][3]*a[3]+a[2]*b[3][2] a[1]*b[3][1] b[3][0]*a[0]
        faddp    ST(1),ST         // b[3][3]*a[3]+a[2]*b[3][2]+a[1]*b[3][1] b[3][0]*a[0]
        faddp    ST(1),ST         // b[3][3]*a[3]+a[2]*b[3][2]+a[1]*b[3][1]+b[3][0]*a[0]
        fstp    [ecx+12]         // c[3] = b[3][3]*a[3]+b[3][2]*a[2]+b[3][1]*a[1]+b[3][0]*a[0]
    }
}