多次push_back vector的快速方法
Fast way to push_back a vector many times
我已经确定了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());
- 使 std::vector 分配对齐内存的现代方法
- 我无法使用C++指针指向类方法返回的 std::vector
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 在 std::vector<无符号字符中存储任意数据的方法>
- 连接和压缩标准::vector<std::字符串的最佳方法>
- C++中的多维数据集:从 std::vector 的 2D 数据到 std::vector 的 2D 网格的最干净方法?
- 向后迭代 std::array 或 std::vector 的正确方法是什么?
- 使用 std::vector::swap 方法在C++中交换两个不同的向量是否安全?
- 有没有更快的方法可以在 std::vector 中插入元素
- 为什么 vector 的方法调整大小会创建一个额外的对象?
- 将vector<vector<double>>从x86平台中创建的一个进程发送到x64中构建的另一个进程的最快方法是什么
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 释放 std::vector 中指针内存的最有效方法是什么?
- 编译错误 std::vector<std::shared_ptr<T>>迭代器和擦除方法
- C++ std::vector 赋值方法
- 使用虚拟变量对 std::vector 内部循环进行切片的最佳方法
- 如何在不使用 vector::erase() 的情况下编写自定义 Vector 方法来删除元素?
- STL vector.insert 方法期望_InputIterator作为参数
- 动态创建 std::vector 并将其传递给另一个函数的各种方法
- 从 std::vector 创建 OpenCV 垫子的有效方法