繁体   English   中英

C++:为 std::vector 分配内存,然后并行初始化其元素

[英]C++: Allocate memory for an std::vector then initialize its elements in parallel

我有一个用例,用于创建一个包含许多元素的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] = ...东西。

有没有办法在不初始化任何元素的情况下分配/“初始化”一个向量,然后并行填充/初始化所有元素?

您的选择是:

执行调整大小后,您可以按常规方式使用 OpenMP。

这取决于你的类型 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)));

我强烈建议不要使用最后一个选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM