我有一个用许多元素创建std::vector
的用例,每个元素都是简单但非基本的类型(POD结构)。向量和类型足够大/复杂,如下所示:
std::vector<U> v;
v.resize(1000000000);
for(size_t i=0;i<v.size();++i){/* initialize v[i] */}
resize
的调用速度很慢。而且这很浪费,因为resize
是默认初始化所有这些条目的,然后循环进行,并将它们全部设置为正确/有用的值。
我想做的是为向量分配所有内存,但不初始化任何条目,然后并行进行并初始化所有条目,例如使用OpenMP
std::vector<U> v;
v.reserve(1000000000);
#pragma omp parallel for
for(size_t i=0;i<v.size();++i){/* initialize v[i] */}
但是,reserve
实际上并没有改变v
的大小,因此我不得不在循环中继续执行push_back
,这将不会保持元素(在我的用例中很重要);我真的很想在循环体内编写类似v[i] = ...
的内容。
有没有一种方法可以在不初始化任何元素的情况下分配/“初始化”向量,然后并行填充/初始化所有元素?
答案 0 :(得分:4)
您的选择是:
std::vector
执行调整大小后,可以按常规方式使用OpenMP。
答案 1 :(得分:3)
这取决于类型U的默认构造函数。 如果默认构造函数便宜,那么几乎不可能获得并行化的任何东西。
struct U {
int a, b, c;
U():a(0), b(1), c(2) {}
};
如果您的默认构造函数很昂贵,则将其分为两部分会更有意义:一个用于默认初始化,一个用于实际初始化的函数。
struct U {
vector<int> a;
U() {}
void init(int n) { a.resize(n); }
};
在这两种选择中,很难对向量进行常规的调整大小或分配调用。
如果您确实对使用这种方法有所了解,则可以对数组使用reinterpret_cast。这样,默认的构造函数将不会被调用。
U * u_array = reinterpret_cast<U*>(malloc(100*sizeof(U)));
我强烈建议不要使用最后一个选项。