重置std::discrete_distribution内部状态是否会降低随机数质量?
我通过std::discrete_distribution迭代生成随机数,若每次迭代都重置该分布的内部状态(等价于在循环内创建std::discrete_distribution对象),随机数质量是否会下降?代码示例如下:
// inputs: // int n_samples // int n_energies // double energies[n_energies] std::mt19937_64 generator; for (int i = 0; i < n_samples; ++i ) { std::discrete_distribution<int> d(energies, energies + n_energies); int index = d(generator); // DO SMTH WITH INDEX // energies array may change between iterations here. }
由于energies数组可能随算法流程不可预测地变化,存在两种边界情况:一是每次迭代energies都变化,此时上述代码可行;二是energies完全不变,即概率相同时重置分布内部状态,这种情况下生成的随机数质量是否劣于不重置状态(将分布对象创建在循环外)的情况?
核心结论:随机数质量不会下降,仅存在性能差异,分两种情况具体说明:
当
energies每次迭代都变化时:循环内创建std::discrete_distribution是唯一可行的方案,因为分布的概率权重已经改变,必须重新初始化分布来适配新的权重,这种情况下生成的随机数完全符合新的概率分布,不存在质量问题。当
energies完全不变时:循环内重复创建分布(重置内部状态),和循环外创建一次分布的随机数统计质量完全一致。std::discrete_distribution的内部状态主要是缓存概率权重的预处理结果(比如归一化后的概率、前缀和数组),用来提升采样效率。重置状态只是重新执行一次预处理,不会影响采样时从随机数生成器(mt19937_64)获取熵的过程,最终生成的随机数依然严格符合指定的离散概率分布,随机性和循环外创建分布的情况没有区别。
唯一的区别是性能:循环内重复创建分布会重复执行概率归一化、前缀和计算等操作,运行效率比循环外创建一次分布要低,但这完全不影响随机数的质量。
内容的提问来源于stack exchange,提问作者user2052436

