我有一個着色器,我需要優化(與大量的矢量操作),我正在試驗SSE指令,以便更好地瞭解問題。幫助海灣合作委員會與自動矢量化
我有一些非常簡單的示例代碼。使用USE_SSE
定義它使用顯式的SSE內在函數;沒有它我希望GCC會爲我做這項工作。自動矢量化感覺有點挑剔,但我希望它能爲我節省一些頭髮。
編譯器和平臺是:gcc 4.7.1(tdm64),目標x86_64-w64-mingw32和Ivy Bridge上的Windows 7。
下面是測試代碼:
/*
Include all the SIMD intrinsics.
*/
#ifdef USE_SSE
#include <x86intrin.h>
#endif
#include <cstdio>
#if defined(__GNUG__) || defined(__clang__)
/* GCC & CLANG */
#define SSVEC_FINLINE __attribute__((always_inline))
#elif defined(_WIN32) && defined(MSC_VER)
/* MSVC. */
#define SSVEC_FINLINE __forceinline
#else
#error Unsupported platform.
#endif
#ifdef USE_SSE
typedef __m128 vec4f;
inline void addvec4f(vec4f &a, vec4f const &b)
{
a = _mm_add_ps(a, b);
}
#else
typedef float vec4f[4];
inline void addvec4f(vec4f &a, vec4f const &b)
{
a[0] = a[0] + b[0];
a[1] = a[1] + b[1];
a[2] = a[2] + b[2];
a[3] = a[3] + b[3];
}
#endif
int main(int argc, char *argv[])
{
int const count = 1e7;
#ifdef USE_SSE
printf("Using SSE.\n");
#else
printf("Not using SSE.\n");
#endif
vec4f data = {1.0f, 1.0f, 1.0f, 1.0f};
for (int i = 0; i < count; ++i)
{
vec4f val = {0.1f, 0.1f, 0.1f, 0.1f};
addvec4f(data, val);
}
float result[4] = {0};
#ifdef USE_SSE
_mm_store_ps(result, data);
#else
result[0] = data[0];
result[1] = data[1];
result[2] = data[2];
result[3] = data[3];
#endif
printf("Result: %f %f %f %f\n", result[0], result[1], result[2], result[3]);
return 0;
}
這編譯:
g++ -O3 ssetest.cpp -o nossetest.exe
g++ -O3 -DUSE_SSE ssetest.cpp -o ssetest.exe
從明確的SSE版本
除了是有點快有輸出沒有什麼區別。
下面是循環中,第一次明確SSE大會:
.L3:
subl $1, %eax
addps %xmm1, %xmm0
jne .L3
它內聯的呼叫。不錯,或多或少只是直線上升_mm_add_ps
。
陣列版本:
.L3:
subl $1, %eax
addss %xmm0, %xmm1
addss %xmm0, %xmm2
addss %xmm0, %xmm3
addss %xmm0, %xmm4
jne .L3
它使用SSE數學好的,但每個陣列成員上。不是真的好。
我的問題是,我該如何幫助GCC,以便它能更好地優化陣列版本vec4f
?
任何Linux特定的技巧也有幫助,這就是真正的代碼將運行的地方。
注意,'float結果[4]'可能不會在堆棧上排列的16個字節的 - 它發生在這種情況下工作,或'_mm_store_ps'會發生故障。 – 2013-03-18 00:44:48