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

问题描述 投票:4回答:2

我有一个用many元素创建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] = ...的内容。

是否有一种方法可以在不初始化任何元素的情况下分配/“初始化”向量,然后并行填充/初始化所有元素?

c++ vector openmp
2个回答
2
投票

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

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


1
投票

您的选择是:

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

© www.soinside.com 2019 - 2024. All rights reserved.