天天看點

java sse執行個體_使用SSE指令

回答(15)

java sse執行個體_使用SSE指令

2 years ago

SSE指令是特定于處理器的 . 您可以在維基百科上查找哪個處理器支援哪個SSE版本 .

如果SSE代碼更快或更快取決于許多因素:第一個當然是問題是記憶體限制還是CPU限制 . 如果記憶體總線是瓶頸,SSE将無濟于事 . 嘗試簡化整數計算,如果這使代碼更快,它可能受CPU限制,并且你很有可能加快它的速度 .

請注意,編寫SIMD代碼要比編寫C代碼困難得多,并且生成的代碼更難以更改 . 始終保持C代碼為最新,您需要将其作為注釋并檢查彙編代碼的正确性 .

考慮使用類似IPP的庫,它實作了針對各種處理器優化的常見低級SIMD操作 .

java sse執行個體_使用SSE指令

2 years ago

以SSE為例的SIMD允許您對多個資料塊執行相同的操作 . 是以,使用SSE作為整數運算的直接替換,您将無法獲得任何優勢,隻有在您可以同時對多個資料項執行操作時才會獲得優勢 . 這涉及加載一些在記憶體中連續的資料值,執行所需的處理,然後單步執行數組中的下一組值 .

問題:

1如果代碼路徑依賴于正在處理的資料,則SIMD變得更難實作 . 例如:

a = array [index];

a &= mask;

a >>= shift;

if (a < somevalue)

{

a += 2;

array [index] = a;

}

++index;

像SIMD一樣不容易做到:

a1 = array [index] a2 = array [index+1] a3 = array [index+2] a4 = array [index+3]

a1 &= mask a2 &= mask a3 &= mask a4 &= mask

a1 >>= shift a2 >>= shift a3 >>= shift a4 >>= shift

if (a1

// help! can't conditionally perform this on each column, all columns must do the same thing

index += 4

2如果資料不重要,則将資料加載到SIMD指令中是很麻煩的

3代碼是特定于處理器的 . SSE僅适用于IA32(Intel / AMD),并非所有IA32 cpus都支援SSE .

您需要分析算法和資料以檢視它是否可以進行SSE并且需要了解SSE的工作原理 . 英特爾網站上有大量文檔 .

java sse執行個體_使用SSE指令

2 years ago

這種問題是良好的低級分析器必不可少的完美例子 . (像VTune這樣的東西)它可以讓你更加了解熱點所在的位置 .

我的猜測,從你描述的是你的熱點可能是使用if / else計算最小/最大值導緻的分支預測失敗 . 是以,使用SIMD内在函數應該允許您使用最小/最大指令,但是,嘗試使用無分支最小/最大計算可能是值得的 . 這可以通過減少疼痛來實作大部分收益 .

像這樣的東西:

inline int

minimum(int a, int b)

{

int mask = (a - b) >> 31;

return ((a & mask) | (b & ~mask));

}

java sse執行個體_使用SSE指令

2 years ago

如果您使用SSE指令,則顯然僅限于支援這些指令的處理器 . 這意味着x86,可以追溯到奔騰2左右(不記得确切的時候它們被引入,但很久以前)

SSE2,據我所知,是提供整數運算的,有點近一些(Pentium 3?雖然第一款AMD Athlon處理器不支援它們)

在任何情況下,您都有兩種使用這些說明的選項 . 要麼在彙編中編寫整個代碼塊(可能是個壞主意 . 這使得編譯器幾乎不可能優化代碼,而且人類編寫高效的彙程式設計式非常困難) .

或者,使用編譯器可用的内在函數(如果記憶體服務,它們通常在xmmintrin.h中定義)

但同樣,表現可能無法改善 . SSE代碼對其處理的資料提出了額外的要求 . 主要是要記住的是資料必須在128位邊界上對齊 . 加載到同一寄存器中的值之間也應該存在很少或沒有依賴關系(128位SSE寄存器可以容納4個整數 . 将第一個和第二個加在一起并不是最佳的 . 但是将所有四個整數添加到相應的4個整數中另一個登記冊會很快)

使用包含所有低級SSE擺弄的庫可能很誘人,但這也可能會破壞任何潛在的性能優勢 .

我不知道SSE的整數運算支援有多好,是以這也可能是一個可以限制性能的因素 . SSE主要針對加速浮點運算 .

java sse執行個體_使用SSE指令

2 years ago

我們已經實作了一些圖像處理代碼,類似于你所描述的但是在位元組數組上,在SSE中 . 與C代碼相比,加速比較大,取決于精确算法的4倍以上,即使在英特爾編譯器方面也是如此 . 但是,正如你已經提到的那樣有以下缺點:

便攜性 . 代碼将運作在每個類似英特爾的CPU上,是以也運作在AMD上,但不會在其他CPU上運作 . 這對我們來說不是問題,因為我們控制目标硬體 . 切換編譯器甚至64位作業系統也是一個問題 .

你有一個陡峭的學習曲線,但我發現在你掌握了編寫新算法的原則之後并不那麼難 .

可維護性 . 大多數C或C程式員不了解彙編/ SSE .

我的建議是,隻有當你真的需要性能改進時,才能實作它,并且你無法在像intel IPP這樣的庫中找到問題的功能,如果你能解決可移植性問題 .

java sse執行個體_使用SSE指令

2 years ago

我可以從我的經驗中看出,SSE帶來了超過普通c版本代碼的巨大(4倍以上)加速(沒有内聯asm,沒有使用内在函數)但是手動優化的彙程式設計式可以勝過編譯器生成的彙編,如果編譯器可以'弄清楚程式員的意圖(相信我,編譯器不會涵蓋所有可能的代碼組合,他們永遠不會) . 哦,編譯器不能每次都以最快的速度布局它運作的資料 . 但是你需要很多經驗來加速英特爾編譯器(如果可能的話) .

java sse執行個體_使用SSE指令

2 years ago

SSE指令最初隻是在英特爾晶片上,但最近(因為Athlon?)AMD也支援它們,是以如果你對SSE指令集進行編碼,你應該可以移植到大多數x86觸發器 .

話雖如此,除非您已經熟悉x86上的彙程式設計式,否則學習SSE編碼可能不值得 - 更簡單的選擇可能是檢查編譯器文檔并檢視是否有選項允許編譯器自動生成SSE代碼為了你 . 一些編譯器以這種方式很好地矢量化循環 . (聽到英特爾編譯器做得很好,你可能并不感到驚訝:)

java sse執行個體_使用SSE指令

2 years ago

編寫有助于編譯器了解您正在做什麼的代碼 . GCC将了解并優化SSE代碼,例如:

typedef union Vector4f

{

// Easy constructor, defaulted to black/0 vector

Vector4f(float a = 0, float b = 0, float c = 0, float d = 1.0f):

X(a), Y(b), Z(c), W(d) { }

// Cast operator, for []

inline operator float* ()

{

return (float*)this;

}

// Const ast operator, for const []

inline operator const float* () const

{

return (const float*)this;

}

// ---------------------------------------- //

inline Vector4f operator += (const Vector4f &v)

{

for(int i=0; i<4; ++i)

(*this)[i] += v[i];

return *this;

}

inline Vector4f operator += (float t)

{

for(int i=0; i<4; ++i)

(*this)[i] += t;

return *this;

}

// Vertex / Vector

// Lower case xyzw components

struct {

float x, y, z;

float w;

};

// Upper case XYZW components

struct {

float X, Y, Z;

float W;

};

};

隻是不要忘記在建構參數上使用-msse -msse2!

java sse執行個體_使用SSE指令

2 years ago

雖然SSE特定于某些處理器(SSE可能相對安全,SSE2在我的經驗中更少),但您可以在運作時檢測CPU,并根據目标CPU動态加載代碼 .

java sse執行個體_使用SSE指令

2 years ago

SIMD内在函數(例如SSE2)可以加快這種速度,但需要專業知識才能正确使用 . 它們對齊和管道延遲非常敏感;粗心使用會使性能比沒有它們時更糟糕 . 通過簡單地使用緩存預取來確定所有的整數都在L1中,以便您對它們進行操作,您将獲得更加輕松和更直接的加速 .

除非你的功能需要每秒優于100,000,000個整數的吞吐量,否則SIMD可能不值得為你帶來麻煩 .

java sse執行個體_使用SSE指令

2 years ago

隻是簡單地添加之前已經說過的關于不同CPU上可用的不同SSE版本的内容:可以通過檢視CPUID指令傳回的相應功能标志來檢視(有關詳細資訊,請參閱英特爾的文檔) .

java sse執行個體_使用SSE指令

2 years ago

看一下C / C的内聯彙程式設計式,這裡是DDJ article . 除非您100%确定您的程式将在相容平台上運作,否則您應該遵循許多人在此處給出的建議 .

java sse執行個體_使用SSE指令

2 years ago

我同意以前的海報 . 好處可能非常大,但要獲得它可能需要大量的工作 . 有關這些說明的英特爾文檔超過4K頁面 . 您可能想要從Ocali Inc.免費檢視EasySSE(c包裝庫,内在執行個體) .

我認為我與EasySSE的關系很明确 .

java sse執行個體_使用SSE指令

2 years ago

我不太喜歡集會 . 正如Skizz所指出的那樣,使用SSE很可能需要對資料進行仔細的重組,而且這種好處往往是值得懷疑的 .

編寫非常小的循環并保持資料組織非常緊密并且依賴編譯器為您執行此操作可能會好得多 . 英特爾C編譯器和GCC(自4.1版)都可以自動矢量化您的代碼,并且可能比您做得更好 . (隻需在您的CXXFLAGS中添加-ftree-vectorize . )

Edit :我應該提到的另一件事是,有幾個編譯器支援彙編内部函數,IMO可能比asm()或__asm {}文法更容易使用 .