2001-07 << 2001-08 >> 2001-09

2001-08-16 (木)

*MMXで最適化

昨日,MMX化をした部分を最適かできないか見直してみました.まだ,ちょっと高速化できそうです.

movd	mm0, [eax]
movd	mm1, [ebx]
punpcklbw	mm0, mm3
punpcklbw	mm1, mm3
pmullw		mm0, mm4 // *=α
pmullw		mm1, mm5 // *=(255-α)
psrlw		mm0, 8 // >>=8
psrlw		mm1, 8 // >>=8
paddusw		mm0, mm1  // +=mm1
packuswb	mm0, mm3
movd		[edx], mm0

半透明合成用のループの中が上のようになってます.こうすると,Pentiumなら2命令ずつ同時に実行されるみたいですね.加算の後にシフトした方がコードのサイズが小さくなる分いい気がします.あとは,まだMMXレジスタが余ってるので,64ビットずつ処理した方がよさそうです.

void alpha_brend(BMSCR* des,BMSCR* src1, BMSCR* src2, int alpha)
{
DWORD *d,*s1,*s2;
DWORD	alpha2;
int siz=(des->sx*3*des->sy)&rt;&rt;3;
d=(DWORD*)des->pBit;
s1=(DWORD*)src1->pBit;
s2=(DWORD*)src2->pBit;
alpha*=0x01010101;
alpha2=~alpha;
_asm{
mov		eax, s1
mov		ebx, s2
mov		edx, d
mov		ecx,siz //ループ用
pxor	mm3, mm3
movd	mm4, alpha2
movd	mm5, alpha
punpcklbw	mm4, mm3
punpcklbw	mm5, mm3
alpha_loop:
//読む
movq	mm0, [eax]
movq	mm1, [ebx]
//コピー
movq	mm6, mm0
movq	mm7, mm1
//下位32bit
punpcklbw	mm0, mm3
punpcklbw	mm1, mm3
pmullw		mm0, mm4
pmullw		mm1, mm5
paddusw		mm0, mm1
psrlw		mm0, 8
//上位32bit
punpckhbw	mm6, mm3
punpckhbw	mm7, mm3
pmullw		mm6, mm4
pmullw		mm7, mm5
paddusw		mm6, mm7
psrlw		mm6, 8
//書く
packuswb	mm0, mm6
movq		[edx], mm0
add		eax,8
add		ebx,8
add		edx,8
loop	alpha_loop
emms//END MMX
}
}

出来上がったのがこれ.一応,Celeron500MHzで640*480*24ビット画像を(表示なしで)65FPSくらいで処理できてます.ちょっと長くなったけど,コンパイル後のコードは200バイト未満だし,そんなでもないだろう….まだ,最適化の余地があるかもしれませんが…例えば,加算後のシフトは別の場所でやればペアリング出来て同時に処理できる気もします….最適化ってはまると抜け出せなくなります(爆).α合成くらい,その辺のサンプルもってくれば手っ取り早そうですが,とりあえず,MMXの勉強ということで(^^;それにしても暫く見ない間にずいぶん便利になってますね.アセンブラには手を出さないつもりでいましたが,このくらいなら楽に高速化できて良いですね(^^;.