为何vector上resize-remove比erase-remove更快?测试异常及选型建议
在vector中,erase-remove惯用法是否不如resize-remove高效?
在C++中,从容器中删除多个元素时,erase-remove惯用法是常见方案,同时也存在resize-remove的替代方案讨论。普遍观点认为erase-remove更优,但我的测试显示resize-remove在vector上(略)更快。那么在vector场景下是否应该使用resize-remove?
基准测试代码
#include <benchmark/benchmark.h> #include <algorithm> #include <functional> #include <iostream> #include <random> #include <vector> using namespace std; constexpr size_t N_ELEMS = 1000000; constexpr int MAX_VAL = N_ELEMS / 10; constexpr int THRESH = MAX_VAL / 5 * 3; static vector<int> generate_input() { vector<int> nums(N_ELEMS); std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dist(0, N_ELEMS); std::generate(nums.begin(), nums.end(), std::bind(dist, std::ref(gen))); return std::move(nums); } static void bm_erase_remove(benchmark::State &state) { for (auto _ : state) { state.PauseTiming(); auto nums = generate_input(); state.ResumeTiming(); nums.erase(std::remove_if(nums.begin(), nums.end(), [](int x) { return x < THRESH; }), nums.end()); benchmark::DoNotOptimize(nums); } } BENCHMARK(bm_erase_remove); static void bm_resize_remove(benchmark::State &state) { for (auto _ : state) { state.PauseTiming(); auto nums = generate_input(); state.ResumeTiming(); nums.resize(std::distance( nums.begin(), std::remove_if(nums.begin(), nums.end(), [](int x) { return x < THRESH; }))); benchmark::DoNotOptimize(nums); } } BENCHMARK(bm_resize_remove); BENCHMARK_MAIN();
测试输出
g++编译结果
$ g++ main.cpp -lbenchmark -O3 -pthread $ ./a.out 2023-05-24T20:07:22+08:00 Running ./a.out Run on (16 X 3193.91 MHz CPU s) CPU Caches: L1 Data 32 KiB (x8) L1 Instruction 32 KiB (x8) L2 Unified 512 KiB (x8) L3 Unified 16384 KiB (x1) Load Average: 0.16, 0.14, 0.16 ----------------------------------------------------------- Benchmark Time CPU Iterations ----------------------------------------------------------- bm_erase_remove 822789 ns 759162 ns 838 bm_resize_remove 818217 ns 754749 ns 935
clang++编译结果
$ clang++ main.cpp -lbenchmark -O3 -pthread $ ./a.out Load Average: 0.25, 0.18, 0.17 ----------------------------------------------------------- Benchmark Time CPU Iterations ----------------------------------------------------------- bm_erase_remove 1165085 ns 1074667 ns 611 bm_resize_remove 958856 ns 884584 ns 782
额外信息
- g版本为13.1.1,clang版本为15.0.7
- 运行环境为WSL上的Arch Linux,内核版本为5.15.90.1-microsoft-standard-WSL2
- CPU型号为AMD Ryzen 7 6800H with Radeon Graphics
更新内容
更新:有趣的是,当单独运行基准测试(使用benchmark_filter选项)时,两者结果相当。这是否由缓存导致?缓存机制在此如何作用?
更新(2023/5/25):若交换两个BENCHMARK语句的顺序,结果完全相反。
内容的提问来源于stack exchange,提问作者rhanqtl
相关产品推荐
相关产品推荐

