【问题标题】:C++: Allocate memory for an std::vector then initialize its elements in parallelC++:为 std::vector 分配内存,然后并行初始化其元素
【发布时间】:2020-04-10 08:17:51
【问题描述】:

我有一个用例来创建一个带有 许多 元素的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] = ... 之类的东西。

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

【问题讨论】:

  • 如果你有 POD,那么默认 ctor 什么都不做,不是吗?
  • @SlavasupportsMonica 通常,矢量实现会在 POD 类型上调用 memset,虽然速度很快,但仍会产生一些成本。
  • 如果你知道你需要的大小,为什么不使用老式的数组呢?
  • @Chipster,所以不要把它放在堆栈上。 auto v = std::make_shared&lt;U[]&gt;(1000000000)
  • @Born2Smile,嗯,没错。但这不是唯一的问题。还有dynamically allocated and normal arrays will still default construct的问题,OP表示有兴趣不做。

标签: c++ vector openmp


【解决方案1】:

您的选择是:

  • std::vector 替换为其他选项(例如uvector
  • 使用某种库无需初始化即可调整大小,例如来自 Facebook 的 UninitializedMemoryHacks

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

【讨论】:

    【解决方案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)));
    

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

    【讨论】:

    • 请注意,malloc 解决方案的理想情况是 struct U 仅包含 POD 类型。在U 包含std::vector 列出的情况下,您必须在free 在您的malloc'd 数组上调用之前,在U 中释放由vector 持有的资源。更不用说在你的数组中构建 U 的箍了。
    • 你是完全正确的。当你使用 reinterpret_cast 时,你真的需要知道你在做什么。
    猜你喜欢
    • 2012-06-09
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2020-10-07
    • 2017-03-15
    • 1970-01-01
    • 2013-06-06
    • 2021-10-26
    相关资源
    最近更新 更多