多次push_back vector的快速方法

Fast way to push_back a vector many times

本文关键字:方法 vector push back 多次      更新时间:2023-10-16

我已经确定了c++代码中的瓶颈,我的目标是加快它的速度。如果一个条件成立,我将物体从一个向量移动到另一个向量。

在python中,python的方法是使用列表推导式:

my_vector = [x for x in data_vector if x > 1]

我已经在c++中破解了一种方法,它工作得很好。然而,我在while循环中调用了数百万次,它很慢。我不太了解内存分配,但我认为我的问题与使用push_back一次又一次地分配内存有关。是否有一种方法来分配我的内存不同,以加快这段代码?(在for循环完成之前,我不知道my_vector应该有多大)。

std::vector<float> data_vector;
// Put a bunch of floats into data_vector
std::vector<float> my_vector;
while (some_condition_is_true) {
    my_vector.clear();
    for (i = 0; i < data_vector.size(); i++) {
        if (data_vector[i] > 1) {
            my_vector.push_back(data_vector[i]);
        }
    }
    // Use my_vector to render graphics on the GPU, but do not change the elements of my_vector 
    // Change the elements of data_vector, but not the size of data_vector
}

最初使用std::copy_if,并将data_vector.size()保留给my_vector(因为这是您的谓词可能求值为真的元素的最大可能数量):

std::vector<int> my_vec;
my_vec.reserve(data_vec.size());
std::copy_if(data_vec.begin(), data_vec.end(), std::back_inserter(my_vec),
    [](const auto& el) { return el > 1; });

请注意,如果您期望谓词求值为true的次数远少于data_vector的大小,则可以避免在这里调用reserve

虽然其他人为您的查询发布了各种伟大的解决方案,但似乎仍然没有太多的内存分配解释,您不太了解,所以我想与您分享我对这个主题的了解。希望对你有帮助。

首先,在c++中,有几种类型的内存:stack, heap, data segment

Stack用于局部变量。有一些重要的特性与之相关,例如,它们会自动回收,对它的操作非常快,它的大小是操作系统相关的,并且很小,以至于在stack中存储一些KB的数据可能会导致内存溢出,等等。

Heap的内存可以全局访问。至于它的重要特性,我们有,如果需要,它的大小可以动态扩展,它的大小更大(比stack大得多),对它的操作比stack慢,需要手动释放内存(在现在的操作系统中,内存会在程序结束时自动释放),等等。

Data segment用于全局变量和静态变量。事实上,这块内存可以被分成更小的部分,例如BBS。

在您的示例中,使用vector。实际上,vector的元素存储在它的内部动态数组中,这是一个具有动态数组大小的内部数组。在早期的c++中,可以在stack内存上创建动态数组,但是现在不再是这样了。要创建动态数组,必须在heap上创建它。因此,vector的元素存储在heap的内部动态数组中。实际上,要动态地增加数组的大小,需要一个进程,即memory reallocation。但是,如果一个vector用户不断扩大他的vector,那么reallocation开销成本将会很高。为了处理这个问题,vector将首先分配一块大于当前需求的内存,即分配内存以供将来使用。因此,在您的代码中,并不是每次调用push_back()时都执行memory reallocation。但是,如果要复制的vector非常大,那么为将来使用保留的内存将不够。然后出现memory allocation。为了解决这个问题,可以使用vector.reserve()

我是一个新手。希望我的分享没有出错。

运行代码两次,第一次只计算需要多少个新元素。然后使用reserve来分配所需的所有内存。

while (some_condition_is_true) {
    my_vector.clear();
    int newLength = 0;
    for (i = 0; i < data_vector.size(); i++) {
        if (data_vector[i] > 1) {
            newLength++;
    my_vector.reserve(newLength);
    for (i = 0; i < data_vector.size(); i++) {
        if (data_vector[i] > 1) {
            my_vector.push_back(data_vector[i]);
        }
    }
    // Do stuff with my_vector and change data_vector
}

我怀疑分配my_vector是问题所在,特别是如果while循环执行多次,因为my_vector的容量应该很快就会足够。

但是为了确保您可以在my_vector中保留与data_vector的大小相对应的容量:

my_vector.reserve(data_vector.size());
while (some_condition_is_true) {
    my_vector.clear();
    for (auto value : data_vector) {
      if (value > 1)
          my_vector.push_back(value);
    }
}

如果您在Linux上,您可以为my_vector保留内存,以防止std::vector重新分配,这在您的情况下是瓶颈。请注意,预留不会因为过度使用而浪费内存,因此对预留值的任何粗略的上限估计都将符合您的需求。在您的例子中,data_vector的大小就足够了。while循环之前的这行代码应该修复瓶颈:

my_vector.reserve(data_vector.size());
相关文章: