プロが教えるわが家の防犯対策術!

現在、できるだけ速く、距離計算を行いたいと考えています。
具体的には、8bit符号なし整数列の距離計算です。
SSEを利用するのが速いので、 _mm_sad_epu8()を使って組みました。

確かに高速に動作しておりますが、
本当はSAD(絶対誤差の総和)ではなく、SSD(2乗誤差の総和)を求めたいのです。

8bitの符号なし整数列を32bitの符号付き整数列に置き換えてから、
計算するのだとは思いますが、どのように組めば効率が良いのか分かりません。

計算の流れは、
・8bit→32bit
・32bit整数列の差分
・32bit整数列の乗算(2乗)
・32bit整数列の総和
となると思いますが、
8bit→32bitを行う関数も見当たらないですし、
符号付き32bit整数列の乗算関数も見当たりません。

どなたかご存知であれば、教えていただけると幸いです。

A 回答 (1件)

 こんにちは。



 かじり程度で、mmx/sseを使用した事があるだけなのですが・・・。一応お話だけでも。
 乗算の方は色々有りすぎて、分からないのですが、

>>8bit→32bitを行う関数

 の方は pinsrw と言う命令が、xmm/mmレジスタの任意の場所に向かってデータを置けるので、其れを利用して並べると言うのなら出来ます。
 対応する関数は、

 PINSRW __m64 _mm_insert_pi16 (__m64 a, int d, int n)
 PINSRW __m128i _mm_insert_epi16 ( __m128i a, int b, int imm) 

 ですが、ストレートに書いてしまった方が楽だと思います。
 アラはあるとは思いますが、其処は勘弁です。本当に早いかどうかは不明です・・・。

// simdblast.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include "emmintrin.h"

__m128i ui8_to_i32(const unsigned __int8 buf_i8[4])
{
__declspec(align(16)) __m128i mem;
__asm
{
//pushad

xor ecx, ecx
mov esi, buf_i8
mov eax, [esi]

mov cl, al
pinsrw xmm0, ecx, 0

mov cl, ah
pinsrw xmm0, ecx, 2

shr eax, 16

mov cl, al
pinsrw xmm0, ecx, 4

mov cl, ah
pinsrw xmm0, ecx, 6

movaps mem, xmm0
//movups mem, xmm0

//popad

emms
}
return mem;
}

int _tmain(int argc, _TCHAR* argv[])
{
__declspec(align(16)) __m128i a = {5,6,7,8};
__declspec(align(16)) __m128i b = {1,2,3,4};

::printf("1バイト\n");
for(int i = 0; i < 4; ++i)
{
::printf("[a : %d][b : %d]\n", a.m128i_u8[i], b.m128i_u8[i]);
}

//8bit→32bitへ変換
a = ::ui8_to_i32(a.m128i_u8);
b = ::ui8_to_i32(b.m128i_u8);

::printf("4バイト\n");
for(int i = 0; i < 4; ++i)
{
::printf("[a : %d][b : %d]\n", a.m128i_i32[i], b.m128i_i32[i]);
}

return 0;
}
    • good
    • 0
この回答へのお礼

御礼が遅くなって申し訳ありません。
ソースまで紹介していただき非常に助かりました。
何とか組めそうです。

本当にありがとうございました。

お礼日時:2009/02/20 23:20

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!