如何解决正确使用 RDRAND片上生成器作为 std::random_device 和 Visual C++ 的随机库
我希望能够使用硬件随机数生成器,如果可用,无论是英特尔还是 amd 运行代码,以及 C++ 随机库:
void randomDeviceBernouilli(double bernoulliParameter,uint64_t trialCount) {
std::random_device randomDevice;
std::cout << "operator():" << randomDevice() << std::endl;
std::cout << "default random_device characteristics:" << std::endl;
std::cout << "minimum: " << randomDevice.min() << std::endl;
std::cout << "maximum: " << randomDevice.max() << std::endl;
std::cout << "entropy: " << randomDevice.entropy() << std::endl;
std::bernoulli_distribution bernoullidist(bernoulliParameter);
uint64_t trueCount{ 0ull };
for (uint64_t i = 0; i < trialCount; i++)
if (bernoullidist(randomDevice))
trueCount++;
std::cout << "Success " << trueCount << " out of " << trialCount << std::endl;
const double successRate = (double)trueCount / (double)trialCount;
std::cout << "Empirical: " << std::fixed << std::setprecision(8) << std::setw(10) << successRate << " Theoretical: " << bernoulliParameter << std::endl;
}
根据this article,entropy()
应该在没有 rdrand 的 cpu 上返回 0,例如 i7-2670qm ivy 桥(我已经在其上测试过 -rdrand 首次出现在其后继产品 Sandy桥),但在 Visual Studio 中始终为 32,如 here 所述。有人建议,缺少随机设备可能会导致 operator()
抛出异常,但这也不会发生。
例如可以使用内在的 int _rdrand32_step (unsigned int* val)
,但它只能从均匀分布中提取,我需要能够利用 C++ 随机库中可用的分布。
在 Visual Studio (2017,2019) 中,将硬件随机数生成器 (rdrand) 与 C++ 的 random
库一起使用的正确方法是什么?
解决方法
在我看来,您应该创建自己的随机数引擎,以供 <random>
中的所有可用发行版使用。
类似的东西
#include <exception>
#include <immintrin.h>
#include <iostream>
#include <limits>
#include <ostream>
#include <random>
#include <stdexcept>
#include <string>
using namespace std::string_literals;
class rdrand
{
public:
using result_type = unsigned int;
static constexpr result_type min() { return std::numeric_limits<result_type>::min(); }
static constexpr result_type max() { return std::numeric_limits<result_type>::max(); }
result_type operator()()
{
result_type x;
auto success = _rdrand32_step(&x);
if (!success)
{
throw std::runtime_error("rdrand32_step failed to generate a valid random number");
}
return x;
}
};
int main()
try
{
auto engine = rdrand();
auto distribution = std::bernoulli_distribution(0.75);
// Flip a bias coin with probability of heads = 0.75
for (auto i = 0; i != 20; ++i)
{
auto outcome = distribution(engine);
std::cout << (outcome ? "heads"s : "tails"s) << std::endl;
}
return 0;
}
catch (std::exception const& exception)
{
std::cerr << "Standard exception thrown with message: \""s << exception.what() << "\""s << std::endl;
}
catch (...)
{
std::cerr << "Unknown exception thrown"s << std::endl;
}
rdrand
指令是否可用应该是类的外部。您可以在 main
中添加代码进行测试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。