我尝试了这些代码,来比较std::copy
和std::string
的构造函数。
#include <chrono>
#include <iostream>
#include <vector>
void construct_test() {
std::vector<uint8_t> raw_data;
for (int i = 0; i < 1000 * 1024; i++) {
raw_data.push_back(i % 256);
}
auto start = std::chrono::high_resolution_clock::now();
std::string target_data;
target_data = std::string(raw_data.begin(), raw_data.end());
auto finish = std::chrono::high_resolution_clock::now();
std::cout << "construct: " << std::chrono::duration_cast<std::chrono::microseconds>(finish -
start)
.count()
<< "us" << std::endl;
}
void copy_test() {
std::vector<uint8_t> raw_data;
for (int i = 0; i < 1000 * 1024; i++) {
raw_data.push_back(i % 256);
}
auto start = std::chrono::high_resolution_clock::now();
std::string target_data;
target_data.resize(raw_data.size());
std::copy(raw_data.begin(), raw_data.end(), target_data.begin());
auto finish = std::chrono::high_resolution_clock::now();
std::cout << "copy: " << std::chrono::duration_cast<std::chrono::microseconds>(finish -
start)
.count()
<< "us" << std::endl;
}
int main() {
construct_test();
copy_test();
return 0;
}
字符串
我得到的结果是:
construct: 6245us
copy: 1087us
型std::copy
的速度提升6倍!
这是符合预期的吗?如果是,原因是什么?
我搜索了很多将向量转换为字符串的方法,但没有人提到std::copy
的方法。我应该用这种方式吗?有什么缺点吗?
1条答案
按热度按时间r3i60tvu1#
正如评论者所指出的,你的测试方法有很大的缺陷。一般来说,您必须多次运行操作(可能是数百万或数十亿次)才能获得有意义的结果。否则,您运行基准测试的顺序和调度等可能会给你带来截然不同的结果。
steady_clock
而不是high_resolution_clock
进行基准测试(尽管在这种情况下这不太可能产生重大影响)construct_test()
和copy_test()
的顺序会得到one function run faster than the other。您可以使用google/benchmark(由QuickBench使用)来获得更有意义的结果。
除了您使用的两种方法之外,至少还有两种方法可以创建/覆盖字符串:
字符串
对于clang 15,libstdc++,-O3,我们得到以下benchmark results:x1c 0d1x的数据
std::string
构造函数是最好的,无论是否首先进行了不必要的默认初始化。前两种方法在内部使用std::memcpy
,这应该是复制内存最快的方法。std::copy
较慢,可能是因为.resize()
需要先将内存清零,并且没有很好地优化到memcpy
,而是优化到矢量化内存操作。.assign
的速度要慢得多,可能是因为与std::copy
相比,部分循环展开较少,所以除了复制内存之外,还有很多开销。即使使用适当的基准测试,您也可以看到意想不到的和戏剧性的差异,并且只有在查看组装时才能理解事情。