我必须暂时处理和存储数据。目前,当达到最大元素时,我使用std::vector::push_back
添加数据和std::vector::erase
来擦除元素。我的问题是我必须处理大量数据,并且当达到最大数量时,擦除似乎达到了性能。所以我决定每隔y ms添加数据并擦除x个元素,作为优化。首先,我还在向量中保留了一定数量。我使用向量,因为我需要const double *std::vector<T>::data()
函数将数据传递到其他地方,我不能进行任何转换/复制或任何事情。它必须快速。
std::vector<double> data;
size_t max; // there are millions of elements, e.g. 2000000
data.reserve(max);
// happens every x microseconds
void receive(double val) {
data.push_back(val);
}
// timed every x ms
void update() {
if (data.size() > max)
data.erase(data.begin(),data.end()+(data.size()-max));
}
我的问题是:我怎样才能提高效率?通过使用另一个容器?是否仍然可以将容器转换为const double *
?
我刚才意识到我总是超过这个设置,这可能是性能下降的原因吗?以下代码是否会解决问题?
if (data.size() > max*0.8)
data.erase(data.begin(),data.begin()+(data.size()-max*0.8));
提前致谢!
答案 0 :(得分:1)
正如我在评论中所说,你的要求确实让你装箱。我唯一知道的容器就是std::vector
。
有两个与std::vector
相关的时间浪费。第一种是当你尝试push_back
已经处于其保留容量的向量时;必须分配新缓冲区,并将旧缓冲区内容复制到新缓冲区。您可以通过在达到容量之前擦除元素来轻松避免这种情况。第二个是从矢量末尾以外的任何地方删除;这需要将元素从缓冲区中的旧位置复制到新位置。 这部分是不可避免的。您唯一的选择是尽可能少地删除,尽可能多地删除元素。
这是一个为您提供两种条件的模式:
void receive(double val) {
static const size_t drop_size = max / 2;
if (data.size() == data.capacity()) {
data.erase(data.begin(), data.begin() + drop_size);
}
data.push_back(val);
}
只要缓冲区变满,就会丢弃一部分数据。我已经任意选择了max / 2,但您可以调整该阈值以满足您的实际要求。
一个好的编译器会在erase
期间优化元素的复制,但是你可以用memcpy
自己做得更好。在这种情况下,您可以使用以下内容替换erase
:
memcpy(&(data[0]), &(data[drop_size]), sizeof(double) * (data.size() - drop_size));
data.resize(data.size() - drop_size);
在决定使用它之前,你应该对此进行基准测试。 我不知道任何vector
实现在调整大小时会降低向量的容量,但我不认为这是标准的要求。< / strike>编辑:标准包括一个要求,当您调整大小低于当前容量时,迭代器不会失效,这可以保证不会减少容量。