OpenMP 4.0引入了一個名爲「omp simd」的新構造。使用這種構造比舊的「並行」有什麼好處?每個人什麼時候會比另一個人更好?並行vs vs omp simd:何時使用每個?
編輯: 這是一個有趣的與SIMD指令相關的paper。
OpenMP 4.0引入了一個名爲「omp simd」的新構造。使用這種構造比舊的「並行」有什麼好處?每個人什麼時候會比另一個人更好?並行vs vs omp simd:何時使用每個?
編輯: 這是一個有趣的與SIMD指令相關的paper。
鏈接到的標準比較清晰(第13頁,行19 + 20)
當任何線程遇到SIMD構建體,與所述構建體相關聯的 循環迭代可以通過執行線程可用的SIMD通道 。
SIMD
是子線程的東西。爲了更具體一些,在CPU上,你可以想象使用simd
指令來專門請求向量化的循環迭代塊,它們分別屬於相同的線程。它以獨立於平臺的方式公開了單個多核處理器中存在的多級並行性。請參閱intel blog post上的討論(以及加速器內容)。因此,基本上,您需要使用omp parallel
將工作分配到不同的線程,然後這些線程可以遷移到多個核心;然後,您可以使用omp parallel
將工作分配到不同的線程。你會想要使用omp simd
來利用每個核心內的矢量流水線(比如說)。通常omp parallel
會在「外部」去處理粗糙粒度的並行分配工作,並且omp simd
會繞過那裏的緊密循環來利用細粒度的並行。
一個簡單的回答:
OpenMP的只是用來利用多核心多線程。此新擴展simd
允許您在現代CPU(如Intel的AVX/SSE和ARM的NEON)上明確使用SIMD指令。 (請注意,SIMD指令是在單線程和單核心上執行的,但是,對於GPGPU,SIMD的含義可以相當擴展,但是我認爲您不需要考慮GPGPU對於OpenMP 4.0)。
所以,一旦你知道了SIMD指令,就可以使用這個新的構造。
在現代CPU,大致有三種類型的並行性:(1)指令級並行(ILP),(2)線程級並行(TLP),和(3)SIMD指令(我們可以說這是矢量級左右)。
ILP由您的亂序CPU或編譯器自動完成。您可以使用OpenMP的parallel for
和其他線程庫來利用TLP。那麼,SIMD呢?內在函數是一種使用它們的方式(以及編譯器的自動矢量化)。 OpenMP的simd
是使用SIMD的新方法。
舉一個很簡單的例子:
for (int i = 0; i < N; ++i)
A[i] = B[i] + C[i];
上面的代碼計算兩個N維矢量的總和。正如您可以輕鬆看到的,陣列A[]
上沒有(loop-carried) data dependency。這個循環是embarrassingly parallel。
可能有多種方式來並行化該循環。例如,在OpenMP 4.0之前,只能使用parallel for
構造將其並行化。每個線程將在多個內核上執行N/#thread
迭代。
但是,你可能會認爲使用多線程進行這種簡單的添加會是一種矯枉過正。這就是矢量化的原因,這主要是由SIMD指令實現的。
使用SIMD會是這樣:
for (int i = 0; i < N/8; ++i)
VECTOR_ADD(A + i, B + i, C + i);
此代碼假定(1)的SIMD指令(VECTOR_ADD
)是256位或8路(8 * 32位); (2)N
是8的倍數。
8路SIMD指令意味着矢量中的8個項目可以在單個機器指令中執行。請注意,英特爾最新的AVX提供了這種8路(32位* 8 = 256位)矢量指令。
在SIMD中,您仍然使用單個內核(同樣,這僅適用於常規CPU,而不適用於GPU)。但是,您可以在硬件中使用隱藏的並行。現代CPU專門爲SIMD指令提供硬件資源,其中每個SIMD 通道可以並行執行。
您可以同時使用線程級並行。上面的例子可以通過parallel for
進一步並行化。 (但是,我懷疑有多少循環可以真正轉換爲SIMDized循環,OpenMP 4.0規範似乎有點不清楚,因此,實際性能和實際限制將取決於實際編譯器的實現。)
總之,simd
結構允許你使用SIMD指令,反過來,更多的並行可與線程級並行一起利用。不過,我認爲實際的實施會很重要。
編譯器不需要在存在simd子句的情況下在並行區域內進行simd優化。我熟悉的編譯器繼續像以前一樣支持嵌套循環,並行外部向量和內部向量。
過去,OpenMP指令通常用於防止涉及外部並行化循環(帶有collapse子句的多個循環)的循環切換優化。這似乎在少數編譯器中發生了變化。當omp parallel do [for] simd被設置時,OpenMP 4開闢了新的可能性,包括通過一種條帶挖掘優化具有不可矢量化內部循環的並行外部循環。 ifort有時在沒有simd子句的情況下將其報告爲外部循環矢量化。然後,它可以針對比omp parallel do simd少的線程進行優化,這似乎需要比simd向量寬度還要多的線程。可以推斷出這樣的區別,因爲如果沒有simd子句,就會隱式地要求編譯器針對諸如100或300之類的循環計數進行優化,而simd子句要求無條件的simd優化。 當我有一個24核心平臺時,gcc 4.9 omp並行simd看起來相當有效。
openmp SIMD上升到3.0版本,然後他們放棄了這個概念。我想這個新的編譯指令是爲了與依賴於SIMD某些方面的舊代碼向後兼容。 openmp文檔有沒有什麼可以說的呢? –
它不是'並行simd';你可以使用'parallel'或者'simd',這暗示了區別。見下文。 –
@JD:當然,這是一個錯字。固定,謝謝 –