我想在parallel區域中使用OpenMP還原條款,在for回圈之外。根據OpenMP參考文獻,還原子句可以在parallel區域中使用,因此不需要for回圈或sections。
然而,當在parallel區域中使用OpenMP的reduction(min:...)時,我得到了不正確的結果。然而,如果我對還原(max:...)/code>使用完全相同的結構,結果是正確的。如果我對最小還原使用一個回圈(#pragma omp for reduction (min:...)),結果是正確的,但我認為這應該是不必要的。下面是我的代碼:
#include <mp.h>
#include <iostream>
#include <limit>
#include <algorithm>
int main(){
auto minVar { std::numeric_limits<int> ::max() };
auto maxVar { std::numeric_limits<int> ::min() };
auto minVarLoop { std::numeric_limits<int> ::max() };
#pragma omp parallel。
{
int threadNo { omp_get_thread_num() };
#pragma omp reduction (min:minVar)
minVar = std::min(minVar, threadNo)。
//minVar = minVar < threadNo ? minVar : threadNo; //也不作業。
#pragma omp for reduction(min:minVarLoop)
for (int i=0; i<omp_get_num_threads(); i){
minVarLoop = std::min(minVarLoop, threadNo)。
}
#pragma omp reduction (max:maxVar)
maxVar = std::max(maxVar, threadNo)。
}
std::cout
<< "min thread num: " << minVar
<< "
最大執行緒數:" << maxVar
<< "
最小執行緒數來自回圈。" << minVarLoop
<<"
"。
return 0;
在16個執行緒的情況下,預期的輸出結果是
min thread num: 0
最大執行緒數。15
最小執行緒數來自Loop。0最小執行緒數: 0
我得到的輸出結果是
min thread num: 12 // or any other number between 0 and 15.
最大執行緒數。15
最小執行緒數來自Loop。0
我在Ubuntu 21.04上使用10.3.0版的g 進行編譯,只使用了-fopenmp的標志。
我忽略了什么?
編輯:不初始化minVar,即使用int minVar;可以使其作業,但我覺得這不是一個令人滿意的解決方案。此外,嘗試用maxVar進行同樣的操作,會使這些結果不正確。哦,我的天。
uj5u.com熱心網友回復:
你正在使用一個編譯器還不支持的功能。 如果你用-Wall編譯你的代碼,你會看到GCC 10.3.0顯示這樣的警告:
red.cc:15: warning: ignoring '#pragma omp reduction' [-Wunknown-pragmas]
15 | #pragma omp reduction(min:minVar)
|
red.cc:24: warning: ignoring '#pragma omp reduction' [-Wunknown-pragmas]
24 | #pragma omp reduction(max:maxVar)
|
如果你更正代碼,就像我在下面展示的使用正確的拼寫(見scope Construct),編譯器仍然會反對,因為它還不支持5.1版本的OpenMP API:
red.cc:15: warning: ignoring '#pragma omp scope' [-Wunk unknown-pragmas]
15 | #pragma omp scope reduction(min:minVar)
|
red.cc:24: warning: ignoring '#pragma omp scope' [-Wunknown-pragmas]
24 | #pragma omp scope reduction (max:maxVar)
|
那么正確的拼寫方式是這樣的:
int main(){
auto minVar { std::numeric_limits<int> ::max() };
auto maxVar { std::numeric_limits<int> ::min() };
auto minVarLoop { std::numeric_limits<int> ::max() };
。
{
int threadNo { omp_get_thread_num() };
minVar = std::min(minVar, threadNo)。
//minVar = minVar < threadNo ? minVar : threadNo; //也不作業。
for (int i=0; i<omp_get_num_threads(); i){
minVarLoop = std::min(minVarLoop, threadNo)。
}
maxVar = std::max(maxVar, threadNo)。
}
std::cout
<< "min thread num: " << minVar
<< "
最大執行緒數:" << maxVar
<< "
最小執行緒數來自回圈。" << minVarLoop
<<"
"。
return 0;
不同的結果是由于一個競賽條件造成的。 不要問為什么你得到的結果是正確的最大,我確實得到不同的結果,任何時候,我運行的代碼。
你的代碼的另一個正確的版本(不需要對OpenMP API的5.1版本的出血邊緣支持)是這樣的:
#include <omp.h>
#include <iostream>
#include <limit>
#include <algorithm>
int main(){
auto minVar { std::numeric_limits<int> ::max() };
auto maxVar { std::numeric_limits<int> ::min() };
auto minVarLoop { std::numeric_limits<int> ::max() };
#pragma omp parallel reduction(min:minVar) reduction(max:maxVar)
{
int threadNo { omp_get_thread_num() };
minVar = std::min(minVar, threadNo)。
#pragma omp for reduction(min:minVarLoop)
for (int i=0; i<omp_get_num_threads(); i){
minVarLoop = std::min(minVarLoop, threadNo)。
}
maxVar = std::max(maxVar, threadNo)。
}
std::cout
<< "min thread num: " << minVar
<< "
最大執行緒數:" << maxVar
<< "
最小執行緒數來自回圈。" << minVarLoop
<<"
"。
return 0;
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/308340.html
標籤:
上一篇:Java中懸空和調度器的競賽條件
