微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

正确使用 RDRAND片上生成器作为 std::random_device 和 Visual C++ 的随机库

如何解决正确使用 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 articleentropy() 应该在没有 rdrandcpu 上返回 0,例如 i7-2670qm ivy 桥(我已经在其上测试过 -rdrand 首次出现在其后继产品 Sandy桥),但在 Visual Studio 中始终为 32,如 here 所述。有人建议,缺少随机设备可能会导致 operator() 抛出异常,但这也不会发生。

例如可以使用内在的 int _rdrand32_step (unsigned int* val),但它只能从均匀分布中提取,我需要能够利用 C++ 随机库中可用的分布。

此外,代码应使用 AMD cpu 上的硬件生成器。

在 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 举报,一经查实,本站将立刻删除。