C++ OpenMP和std::vector<bool>

7
为什么以下代码对于std::vector of bool不起作用(如预期)? 布尔向量中的某些元素随机为false。 对于int向量,所有内容都正常工作(使用多个循环进行测试)。
我在ubuntu 14.04 64位上使用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;
}

3
https://isocpp.org/blog/2012/11/on-vectorbool - Mansuro
感谢您提供的链接。 - Mr. B0ne
3个回答

7

很可能是因为编译器将vector<bool>转换为位数组。如果您不需要位数组,请改用存储0和1的vector<int>vector<char>


谢谢你,我不知道那个。 - Mr. B0ne

7

vector<bool>是明确的模板特化,它将布尔值打包到某些整数变量的位中。为了使位可由语义正确的下标进行写入,vector<bool>::operator[]返回一些代理对象,该代理对象可转换为bool并具有用于布尔值的赋值运算符。不同索引的代理对象可能引用相同的底层内存,因此不能保证同时访问不同位的线程安全。

要证明这不是编译器错误,请参阅页面上的“数据竞争”部分:

不能保证同时访问不同元素是线程安全的(因为存储字节可能由多个位共享)。

或参阅C++标准的23.2.2节:

  1. 除了vector<bool>之外,在同一序列中不同元素所包含的对象的内容在并发修改时,<...> 实现必须避免数据竞争。
  2. 作为一般规则的例外,对于vector<bool> yy[0] = true可能与y[1] = true竞争。

正如@Anton建议的那样,请使用类型而不是bool


4
除了Sergey和Anton的回答之外,我想指出向量被认为不是线程安全的,正如在数据竞争部分中描述的那样。您可以在http://www.cplusplus.com/reference/vector/vector-bool中找到更多信息。
您的替代方案(正如其他人建议的)要么是使用其他类型的向量,要么保护该语句。
bv[j] = tv[j].test();

使用#pragma omp critical来实现同步。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接