ペアリングによる最適化の解説は後にして、まず下記プログラムを動かして処理時間を見て下さい。
それにしても、プログラムはスパゲッティです。決して読めた代物ではありません。
ただ、あまり速くならない、ペアリングの考えがまだ浅いのでしょうか。
また後で、じっくり考えましょう。
同一カテゴリにない命令は同時実行可能
カテゴリ#1 |
カテゴリ#2 |
PFADD
PFSUB
PFSUBR
PFACC
PFCMPGE
PFCMPGT
PFCMPEQ
PFMIN
PFMAX
PI2FD
PF2ID
PFRCP
PFRSQRT |
PFMUL
PFRCPIT1
PFRSQRIT1
PFRCPIT2 |
後は、基本的にこれ以外のx86命令(ただしFPUレジスタを操作する命令を除く)と同時実行が可能なはずです。

#pragma warning( disable : 4799 ) // Disables EMMS warning for inline assembly
#include "amd3d.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>
typedef struct vector {
float x,y;
} vector;
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]のアドレス
movq mm0,[edi]
// mm0:
a[1]: a[0]
movq mm1,[edi+8]
// mm1:
a[3]: a[2]
movq mm2,[ebx]
// mm2:
b[0]b[1]:
b[0]b[0]
movq mm3,[ebx+8]
// mm3:
b[0]b[3]:
b[0]b[2]
pfmul (m2,m0)
// mm2:
a[1]*b[0]b[1]: a[0]*b[0]b[0]
movq mm4,[ebx+16]
// mm4:
b[1]b[1]:
b[1]b[0]
pfmul (m3,m1)
// mm3:
a[3]*b[0]b[3]: a[2]*b[0]b[2]
movq mm5,[ebx+24]
// mm5:
b[1]b[3]:
b[1]b[2]
pfadd (m2,m3)
// mm2:
pfmul (m4,m0)
// mm4:
a[1]*b[1]b[1]: a[0]*b[1]b[0]
pfacc (m2,m2)
// mm2:
a[3]*b[0]b[3]+a[2]*b[0]b[2]+a[1]*b[0]b[1]+a[0]*b[0]b[0]
pfmul (m5,m1)
// mm4:
a[3]*b[1]b[3]: a[2]*b[1]b[2]
movd [ecx],mm2
// c[i] = mm2
pfadd (m4,m5)
// mm4:
movq mm6,[ebx+32]
// mm6:
b[2]b[1]:
b[2]b[0]
pfacc (m4,m4)
// mm4:
a[3]*b[1]b[3]+a[2]*b[1]b[2]+a[1]*b[1]b[1]+a[0]*b[1]b[0]
movq mm7,[ebx+40]
// mm7:
b[2]b[3]:
b[2]b[2]
pfmul (m6,m0)
// mm6:
a[1]*b[2]b[1]: a[0]*b[2]b[0]
movd [ecx+4],mm4
// c[1] = mm4
pfmul (m7,m1)
// mm7:
a[3]*b[2]b[3]: a[2]*b[2]b[2]
movq mm2,[ebx+48]
// mm2:
b[3]b[1]:
b[3]b[0]
pfadd (m6,m7)
// mm6:
movq mm3,[ebx+56]
// mm3:
b[3]b[3]:
b[3]b[2]
pfacc (m6,m7)
// mm6:
a[3]*b[2]b[3]+a[2]*b[2]b[2]+a[1]*b[2]b[1]+a[0]*b[2]b[0]
movd [ecx+8],mm6
// c[2] = mm6
pfmul (m2,m0)
// mm2:
a[1]*b[3]b[1]: a[0]*b[3]b[0]
pfmul (m3,m1)
// mm3:
a[3]*b[3]b[3]: a[2]*b[3]b[2]
pfadd (m2,m3)
// mm2:
pfacc (m2,m2)
// mm2:
a[3]*b[3]b[3]+a[2]*b[3]b[2]+a[1]*b[3]b[1]+a[0]*b[3]b[0]
movd [ecx+12],mm2
// c[3] = mm2
}
}
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();
_asm{
femms
}
for(n=0;n<100000000;n++)
{
mtrx(a,b,c);
}
_asm{
femms
}
dt2 = GetTickCount();
ddt = (double)(dt2-dt1)/1000.0;
sprintf(buf,"%f %f %f %f\n3DNow!による処理時間は %.3f
秒です",c[0],c[1],c[2],c[3],ddt);
MessageBox(GetDesktopWindow(), buf,"Test 3DNow!",MB_OK);
}