2017-01-14 5 views
1

私は今、SIMDを学び、コンパイラに自分のコードを最適化する方法を考えています。今、私はVisual C++ 2013 x86で遊んでいます。どのようにVCコンパイラを改善するためにSIMDを使ってコードを最適化するのですか?

私は配列を持って、私は別の配列を持っている、と私はこのように計算したい:私は配列は16バイト境界と誰に整列されているコンパイラに伝えたい

void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count) 
{ 
    __declspec(align(16)) float* p1 = inp1; 
    __declspec(align(16)) float* p2 = inp2; 
    __declspec(align(16)) float* ret = arr; 

    while (count > 0) 
    { 
     ret[0] = p1[0] + p2[0]; 
     ret[1] = p1[1] + p2[1]; 
     ret[2] = p1[2] + p2[2]; 
     ret[3] = p1[3] + p2[3]; 

     p1 += 4; 
     p2 += 4; 
     ret += 4; 

     count -= 4; 
    } 
} 

はオーバーレイではありません1つのループは4つの連続フロート数の合計を計算します。

しかし、生成されたコードでは、VCはMOVSS/ADDSSを優先し、私が望むADDPSは使用しません。



LLVM-vs2013ツールチェーンを使用するようにプロジェクトを構成する場合は、ADDPSを使用して合計を計算します。

私はコンパイラ組み込み関数を使ってSIMDコードを書く方法を知っていますが、それは私が望むものではありません。

VCがADDPS命令を使用する必要があるというヒントがもうありますか?



これは完全なコードです。

#include <stdio.h> 
#include <stdlib.h> 

void computeSum(float* __restrict arr, float* __restrict inp1, float* __restrict inp2, int count) 
{ 
    __declspec(align(16)) float* p1 = inp1; 
    __declspec(align(16)) float* p2 = inp2; 
    __declspec(align(16)) float* ret = arr; 

    while (count > 0) 
    { 
     ret[0] = p1[0] + p2[0]; 
     ret[1] = p1[1] + p2[1]; 
     ret[2] = p1[2] + p2[2]; 
     ret[3] = p1[3] + p2[3]; 

     p1 += 4; 
     p2 += 4; 
     ret += 4; 

     count -= 4; 
    } 
} 

int main() 
{ 
    float* inp1 = (float*)_aligned_malloc(sizeof(float) * 128, 16); 
    float* inp2 = (float*)_aligned_malloc(sizeof(float) * 128, 16); 
    float* result = (float*)_aligned_malloc(sizeof(float) * 128, 16); 

    for (int i = 0; i < 128; ++i) 
    { 
     inp1[i] = inp2[i] = i; 
    } 

    computeSum(result, inp1, inp2, 128); 

    for (int i = 0; i < 128; ++i) 
    { 
     printf("%f\t", result[i]); 
    } 

    return 0; 
} 
+0

/arch:SSE(またはそれに類似する)を指定しましたか? – harold

+0

@haroldはい、スイッチ/ arch:SSE2が有効です。 – Sorayuki

+0

ループをアンロールしないで*試しましたか? –

答えて

1

のVisual C++ 2013以降では、x86用/arch:SSE2を使用するようにデフォルト設定されますが、あなたはまだそれが明示的に何か他のものに設定されていないことを確認するために、Visual Studioのプロジェクトの設定を確認する必要があります。 x64では、/arch:SSE2が暗黙です。

Visual C++がシングルレーン(ADDSS)命令ではなくマルチレーン(ADDPSなど)を自動的に生成する唯一の時間は、自動ベクトル化器によるものです。詳細については、MSDNを参照してください。/Qvec-report:2スイッチに特に注意してください。また、デバッグ設定では一般的なように無効化された最適化ではこのようなことは起こりません。

ほとんどのSIMD(マルチレーン)コードジェンは、明示的な組み込み関数を使用した方が優れています。このコーディングスタイルの例の多くは、DirectXMathを参照してください。

+0

レポートを有効にするために、「自動ベクトル化」とパラメータ切り替えを知っていることは私にとって非常に重要です。しかし、いくつかの試行の後、私はオプティマイザにaddpsを使用させることはできません。サンプルコードをお願いしますか?ありがとうございました – Sorayuki

関連する問題