【发布时间】:2023-03-09 05:44:02
【问题描述】:
我测试了以下两种用 100'000 个元素填充向量的方法:
#include <iostream>
#include <vector>
#include <chrono>
using std::cout;
using std::endl;
using std::vector;
using std::chrono::high_resolution_clock;
using std::chrono::duration_cast;
int main()
{
const int n = 100'000;
cout << "Range constructor: " << endl;
high_resolution_clock::time_point t0 = high_resolution_clock::now();
int nums10[n];
for (int i = 0; i < n; ++i) {
nums10[i] = i;
}
vector<int> nums11(nums10, nums10 + n);
high_resolution_clock::time_point t1 = high_resolution_clock::now();
cout << "Duration: " << duration_cast<std::chrono::microseconds>(t1 - t0).count() << endl;
cout << "Fill constructor: " << endl;
t0 = high_resolution_clock::now();
vector<int> nums1(n);
for (int i = 0; i < n; ++i) {
nums1[i] = i;
}
t1 = high_resolution_clock::now();
cout << "Duration: " << duration_cast<std::chrono::microseconds>(t1 - t0).count() << endl;;
}
在我的例子中,范围构造函数的运行速度几乎快了 10 倍(600 微秒对 ~5000 微秒)。
为什么这里会有任何性能差异?据我了解,分配操作的数量相等。使用范围构造函数,将 100'000 个元素分配给数组,然后将它们全部复制到向量中。
这不应该与填充构造函数相同,其中 100'000 个元素首先默认初始化为 0,然后在 for 循环中为所有元素分配它们的“真实”值吗?
【问题讨论】:
-
如果你认为范围构造函数使用了一个简单的循环,那你可能就错了。查看汇编输出以进行验证。提示:除了完全优化的构建,不要费心对任何东西进行基准测试。调试版本会产生完全没有意义的结果。
-
以微秒为单位处理时,性能无关紧要
-
@tadman:当然,“仅对完全优化的构建进行基准测试”的必然结果是“玩具问题通常过于简单,因此请确保编译器不会完全优化所有工作”。如果您不使用结果,或者结果以在编译时可预测的方式使用,则其中一个或两个可能在运行时根本不起作用,即使真实世界的代码确实如此必须做类似的事情(由于缺乏可预测性)。我怀疑您使用的调试版本没有内联
vector的operator[],造成人为差异,但您没有提供构建设置。 -
@ShadowRanger 确实如此,有时您最终会对两个不同的空函数进行基准测试,实际上是在测量您的 CPU 加速和/或热调节的速度。
-
@tadman 不幸的是,我不熟悉组装。如果它没有迭代和复制范围构造函数中的值,你能解释一下实际发生了什么吗?此示例已禁用优化。我知道这种差异在绝对意义上是没有意义的,但我很好奇为什么这里会有差异。
标签: c++ performance optimization vector std