2011-07-31 7 views
0

配列の各項目に適用する基本的な計算機能があります。この関数は2つのベクトルを合計するだけです。SIMDコマンドをコードに導入する際のトラブル

SIMDコマンドを使用して、配列から複数の項目を並行して処理したいと考えました。 http://www.doc.ic.ac.uk/~nloriant/files/scfpsc-pc.pdf

私はここのように配列表記を使用してみました: http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/cpp/mac/optaps/common/optaps_elem_functions.htm

をしかし、これはやった、私は私の場合のために、あまりにも簡単な例のこれらの種類を(彼らは関数呼び出しを含まない)が発見したよう

私のコードを加速しない。私が間違っていることを理解していないし、もっとアセンブリ型のSIMDスタイルに移行する必要がある場合、そこに関数呼び出しを導入するにはどうすればいいですか?

誰でも私に手伝ったり私のニーズのための良いソース私は非常にthakfulになります。

ありがとうございます!


コード例:

これは、アレイ内の各アイテムに適用される基本的な機能である:

float VarFlow::gauss_seidel_step(IplImage* u, int i, float h, float J11, float J12, float J13, float vi){ 

int x = i%u->width; 
int y = i/u->width; 

int start_y, end_y, start_x, end_x; 
int N_num = 0; 

start_y = y - 1; 
end_y = y + 1; 
start_x = x - 1; 
end_x = x+1;   

float temp_u = 0; 

// Sum top neighbor  
if(start_y > -1){    

    temp_u += *((float*)(u->imageData + start_y*u->widthStep) + x); 

    N_num++; 

} 

// Sum bottom neighbor    
if(end_y < u->height){ 

    temp_u += *((float*)(u->imageData + end_y*u->widthStep) + x); 

    N_num++; 

} 

// Sum left neighbor 
if(start_x > -1){    

    temp_u += *((float*)(u->imageData + y*u->widthStep) + start_x); 

    N_num++; 

} 

// Sum right neighbor 
if(end_x < u->width){    

    temp_u += *((float*)(u->imageData + y*u->widthStep) + end_x); 

    N_num++; 

} 

temp_u = temp_u - (h*h/alpha)*(J12*vi + J13); 
temp_u = temp_u/(N_num + (h*h/alpha)*J11); 

return temp_u; 

} Iは__declspecでそれを宣言したい

(ベクター)と呼びましょう。

u_ptr[0:max_i:1] = gauss_seidel_step(imgU, vect[0:max_i:1], h, fxfx_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fxft_ptr[0:max_i:1], v_ptr[0:max_i:1]); 
    v_ptr[0:max_i:1] = gauss_seidel_step(imgV, vect[0:max_i:1], h, fyfy_ptr[0:max_i:1], fxfy_ptr[0:max_i:1], fyft_ptr[0:max_i:1], u_ptr[0:max_i:1]); 

forループの代わりに。

私はこれで方向性を得ることができます(これはおそらく同様の例へのリンクですが)ではなく、完全な解決策です。

ありがとうございます!

+0

になります。 SIMDでの私の経験は20年前ですが、私は効果的なコードを書くことは非常に難しいことです。特に、分岐文( 'if'文)は許可されていますが、達成しようとしている並列性を損なう可能性があります。 –

+0

明示的なSIMDコード(たとえば、組み込み関数を使用する)を使用するのか、インテルのツールの並列拡張を使用するのかを決める必要があります。おそらく、ベクトル化したいコードの簡単な例を投稿することができますか? –

+0

私はSIMDが関数を並行して呼び出すことを許しているとは思えませんが、数学的操作のためだけです。 – James

答えて

3

SIMDと条件付き分岐はうまく混合されません。

条件文をブール値のマスクと乗算に変換します。それは操作をベクトル化するための正しい道をあなたに送ります。

if(end_x < u->width){     
    temp_u += value;  
    N_num++;  
} 

コードのサンプルはここに役立つかもしれない

ltmask = (end_x < u->width); // see _mm_cmplt_ps 
temp_u += ltmask*value; // see _mm_add_ps, _mm_and_ps 
N_num += ltmask; // use _mm_and_ps with a vector of 1.0f 
関連する問題