初始化PRNG内部状态是否耗时?实测std::mt19937无明显差异
问题分析:mt19937两种播种方式的耗时差异无法被strace检测到
你编写了对比std::mt19937两种播种方式的代码,用strace -c计时却没发现显著差异,但std::mt19937在libstdc++中体积达5000字节,疑惑初始化耗时为何无法测量,或是测试方式有误。
核心原因:测试工具strace -c的局限性
strace -c仅统计系统调用的耗时与调用次数,而std::mt19937的初始化(无论是全状态播种还是单值播种)几乎都是用户态计算:仅调用std::random_device时会触发少量系统调用(如读取/dev/urandom),但这部分耗时在两种方案中差异极小;填充引擎内部状态数组的核心逻辑完全在用户态执行,strace -c不会统计这部分时间,自然测不出差异。
次要原因:初始化耗时被后续任务掩盖
代码中后续的std::transform_reduce(并行版本)会执行大量随机数生成操作,其耗时远大于引擎初始化的耗时。即使两种初始化方式有微小差异,也会被后续大任务的耗时“淹没”,导致单次测试无法观测到区别。
正确的测试建议
换用合适的性能分析工具
- 使用
perf stat:它能统计程序的用户态耗时、内核态耗时、指令数等详细指标,可准确捕捉用户态初始化操作的差异。示例命令:perf stat ./your_program - 使用
time命令统计总耗时,需多次运行取平均值以减少系统调度误差:for i in {1..10}; do time ./your_program; done
- 使用
放大初始化操作的耗时占比
将初始化逻辑单独循环执行数万次,放大两种方案的耗时差异,比如修改代码:int main() { std::random_device rand_dev { }; const int iterations = 100000; long long dummy = 0; for (int i = 0; i < iterations; ++i) { #if SEEDING_ENABLED == 1 std::array<int, std::mt19937::state_size> seed_data; std::ranges::generate( seed_data, std::ref( rand_dev ) ); std::seed_seq seq { std::cbegin( seed_data ), std::cend( seed_data ) }; std::mt19937 engine { seq }; #elif SEEDING_ENABLED == 0 std::mt19937 engine { rand_dev( ) }; #endif dummy += engine(); // 防止编译器优化掉初始化 } std::cout << dummy << '\n'; }此时再用
time或perf测试,就能明显看到两种方案的耗时差异。验证编译器优化影响
编译时关闭优化(-O0),避免编译器对初始化逻辑做激进优化,确保测试的是真实的初始化耗时。
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

