64bit整数のエンディアン変換の高速化
http://d.hatena.ne.jp/studiokingyo/20060415#p2
で読んだ記事から
という命令を使うとエンディアン変換が高速化されるとの事を聞いたので試してみた。
PSHUFW
実装は以下のような感じだ。
#define dkcmREVERSE_ENDIAN32(x) \
( (x << 24) | ( (x & 0x0000ff00) << 8) |
( (x & 0x00ff0000) >> 8 ) | (x >> 24) )# define dkcmREVERSE_ENDIAN64(x) (\
(ULONGLONG)dkcmREVERSE_ENDIAN32(
(DWORD) (x & 0x00000000ffffffff) ) << 32 )\
| \
dkcmREVERSE_ENDIAN32((DWORD)(x >> 32)\
){
for(i=0;i<loop_num;i++){
t = rand();
t = dkcmREVERSE_ENDIAN64(t);
}
}
{
for(i=0;i<loop_num;i++){
t = rand();
_asm{
movq mm0,t
PSHUFW mm1,mm0,27
movq mm2,mm1
PSLLW mm1,8
PSRLW mm2,8
pand mm1,mm3
por mm2,mm1
movq t,mm2
}
}
}
Debugモードでは雀の涙ほどの効果が出ているようなのだが・・・
Releaseモードにするとモノの見事に遅い。
ranking_tiemr / clock type : QueryPerformanceClock / compile mode : DEBUG
1 / reverse endian in sse / 209776
2 / reverse endian in c / 224506
インラインアセンブラにすることによってレジスタをpush popしたりでなんらかのオーバーヘッドがかかっているのだと思う。(変換されたアセンブリコードを見ずにこういう憶測を言うことは良くないのだが・・・)
ranking_tiemr / clock type : QueryPerformanceClock / compile mode : RELEASE
1 / reverse endian in c / 116383
2 / reverse endian in sse / 189148
また、PSHUFWを使った私のエンディアン変換の実装が良くないのかもしれない。
私の場合、コレしか思いつかなかったのだが別に高速なPSHUFWを使った実装はあるのだろうかと感じた。
もし、この記事を見た方でご存知の方、思いついた方がいらっしゃいましたら是非、コメントやトラックバックを送っていただけると嬉しいです。