[英]C++ OpenMP and std::vector<bool>
為什么以下代碼對bool的std :: vector不起作用(如所考慮的)? bool-vector中的一些元素是隨機錯誤的。 對於int向量,所有工作正常(使用多於3個循環進行測試)。
我在ubuntu 14.04 64bit上使用g ++ 4.8.4。
#include <iostream>
#include <vector>
using namespace std;
class TestBool
{
public:
TestBool() {}
bool test() {return true;}
int testInt() {return 10;}
};
void testBVec(vector<bool> &bv, size_t loop)
{
cout << "boolvec loop " << loop << endl;
for(size_t i = 0; i < bv.size(); i++) {
if( ! bv[i])
cout << "wholy shit with bool at index " << i << endl;
}
}
void testIntVec(vector<int> &iv, size_t loop)
{
cout << "intVec loop " << loop << endl;
for(size_t i = 0; i < iv.size(); i++) {
if( iv[i] != 10)
cout << "wholy shit with int at index " << i << endl;
}
}
int main()
{
vector<TestBool> tv(10);
size_t loops = 3;
for(size_t i = 0; i < loops; i++ ) {
vector<bool> bv(10);
vector<int> iv(10);
#pragma omp parallel for
for(int j = 0; j < 10; ++j) {
bv[j] = tv[j].test();
iv[j] = tv[j].testInt();
}
testBVec(bv, i+1);
testIntVec(iv, i+1);
}
return 0;
}
vector<bool>
是顯式模板特化,它將布爾值打包成一些整數變量的位。 為了通過語義正確的下標使位可寫, vector<bool>::operator[]
返回一些可轉換為bool
並具有bool
賦值運算符的代理對象 。 不同索引的代理對象可以引用相同的底層內存,因此不能保證對不同位的同時訪問是線程安全的。
對於一個合格的證明,它不是一個編譯器錯誤,see'Data種族一節這個頁面:
不能保證對不同元素的同時訪問是線程安全的(因為存儲字節可以由多個位共享)。
或C ++標准的第23.2.2節:
- 除了
vector<bool>
,同時修改同一序列中不同元素中包含對象的內容時,需要實現以避免數據爭用。- <...>作為一般規則的例外,對於
vector<bool> y
,y[0] = true
可以與y[1] = true
競爭。
正如@Anton建議的那樣,使用bool
以外的類型。
很可能是因為vector<bool>
被編譯器轉換為位數組。 如果你不需要位數組,只需使用vector<int>
或vector<char>
存儲0和1。
除了謝爾蓋和安東的回答之外,我還要指出,已知向量不是線程安全的,如http://www.cplusplus.com/reference/vector/vector-bool中的數據競爭部分所述。
您的替代方案(正如其他人建議的那樣)要么轉到其他類型的向量,要么保護聲明
bv[j] = tv[j].test();
#pragma omp critical
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.