私は今、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;
}
/arch:SSE(またはそれに類似する)を指定しましたか? – harold
@haroldはい、スイッチ/ arch:SSE2が有効です。 – Sorayuki
ループをアンロールしないで*試しましたか? –