/openmp
(啟用 OpenMP 支援)
讓編譯程式處理 #pragma omp
支援 OpenMP 的指示詞。
語法
/openmp
/openmp:experimental
/openmp:llvm
/openmp
備註
#pragma omp
用來指定 指示詞 和 子句。 如果未 /openmp
在編譯中指定,編譯程式會忽略 OpenMP 子句和指示詞。 即使/openmp
未指定,編譯程式仍會處理 OpenMP 函式呼叫。
C++編譯程式目前支援 OpenMP 2.0 標準。 Visual Studio 2019 現在也提供 SIMD 功能。 若要使用 SIMD,請使用 /openmp:experimental
選項進行編譯。 此選項同時啟用一般 OpenMP 功能,以及使用 /openmp
參數時無法使用的 OpenMP SIMD 功能。
從 Visual Studio 2019 16.9 版開始,您可以使用實驗 /openmp:llvm
選項,而不是 /openmp
以 LLVM OpenMP 運行時間為目標。 目前不支持生產程式代碼,因為必要的 libomp DLL 無法轉散發。 選項支援與 /openmp
相同的 OpenMP 2.0 指示詞。 而且,它支援 選項所 /openmp:experimental
支援的所有SIMD指示詞。 它也支持根據 OpenMP 3.0 標準,平行處理迴圈的不帶正負號整數索引。 如需詳細資訊,請參閱 改善Visual Studio中C++的OpenMP支援。
選項 /openmp:llvm
支援 x64 架構。 從 Visual Studio 2019 16.10 版開始,它也支援 x86 和 ARM64 架構。 此選項與或/ZW
不相容/clr
。
使用 /openmp
和 /clr
編譯的應用程式只能在單一應用程式域進程中執行。 不支援多個應用程式域。 也就是說,當模組建構函式 (.cctor
) 執行時,它會偵測是否使用 /openmp
編譯進程,以及應用程式是否載入非預設運行時間。 如需詳細資訊,請參閱 appdomain
、 /clr
(Common Language Runtime 編譯)和 混合元件的初始化。
如果您嘗試將同時使用 /openmp
和 /clr
編譯的應用程式載入至非預設應用程式域, TypeInitializationException 則會在調試程式外部擲回例外狀況,並在 OpenMPWithMultipleAppdomainsException
調試程式中擲回例外狀況。
在下列情況下,也可以引發這些例外狀況:
如果您的應用程式是使用
/clr
編譯,但不是/openmp
,而且會載入至非預設應用程式域,其中進程包含使用/openmp
編譯的應用程式。如果您將
/clr
應用程式傳遞至公用程式,例如 regasm.exe,它會將其目標元件載入非預設應用程式域。
Common Language Runtime 的程式代碼存取安全性無法在 OpenMP 區域中運作。 如果您在平行區域外套用CLR代碼存取安全性屬性,則不會在平行區域中生效。
Microsoft不建議您撰寫 /openmp
允許部分信任呼叫端的應用程式。 請勿使用 AllowPartiallyTrustedCallersAttribute、 或任何 CLR 程式代碼存取安全性屬性。
在 Visual Studio 開發環境中設定這個編譯器選項
開啟專案的 [屬性頁] 對話方塊。 如需詳細資料,請參閱在 Visual Studio 中設定 C ++ 編譯器和組建屬性。
展開 [組態屬性>C/C++>Language 屬性頁。
修改 OpenMP Support 屬性。
若要以程式方式設定這個編譯器選項
- 請參閱 OpenMP。
範例
下列範例顯示線程集區啟動與啟動線程集區之後使用線程集區的影響。 假設 x64、單一核心、雙處理器,線程集區需要大約 16 毫秒才能啟動。 之後,線程集區的成本很少。
當您使用 /openmp
進行編譯時,test2 的第二次呼叫永遠不會執行超過您使用 /openmp-
編譯的時間,因為沒有線程集區啟動。 在一百萬次反覆運算中 /openmp
,版本比 /openmp-
第二次呼叫 test2 的版本快。 在 25 次反覆運算中, /openmp-
和 /openmp
版本都會註冊小於時鐘粒度。
如果您的應用程式中只有一個迴圈,且其執行時間小於 15 毫秒(已針對電腦上的近似額外負荷進行調整), /openmp
可能不適合。 如果比較高,您可能想要考慮使用 /openmp
。
// cpp_compiler_options_openmp.cpp
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
volatile DWORD dwStart;
volatile int global = 0;
double test2(int num_steps) {
int i;
global++;
double x, pi, sum = 0.0, step;
step = 1.0 / (double) num_steps;
#pragma omp parallel for reduction(+:sum) private(x)
for (i = 1; i <= num_steps; i++) {
x = (i - 0.5) * step;
sum = sum + 4.0 / (1.0 + x*x);
}
pi = step * sum;
return pi;
}
int main(int argc, char* argv[]) {
double d;
int n = 1000000;
if (argc > 1)
n = atoi(argv[1]);
dwStart = GetTickCount();
d = test2(n);
printf_s("For %d steps, pi = %.15f, %d milliseconds\n", n, d, GetTickCount() - dwStart);
dwStart = GetTickCount();
d = test2(n);
printf_s("For %d steps, pi = %.15f, %d milliseconds\n", n, d, GetTickCount() - dwStart);
}