乱数ジェネレーター

インテル® oneAPI DPC++ ライブラリー (インテル® oneDPL) の乱数ジェネレーターの使用方法の概要を説明します。

インテル® oneDPL は、以下を含む乱数の生成をサポートしています。

乱数エンジン

乱数エンジンは、シードデータをエントロピー源として使用して疑似乱数を生成します。インテル® oneDPL は、カスタマイズされたエンジン向けにいくつかのクラス・テンプレートを提供しており、これらは <oneapi/dpl/random> ヘッダーで定義されています。

エンジン 説明
linear_congruential_engine

線形合同アルゴリズムを実装します。

subtract_with_carry_engine

キャリー付き減算アルゴリズムを実装します。

discard_block_engine

破棄ブロックアダプターを実装します。

事前定義済み乱数エンジン

事前定義済みの乱数エンジンは、乱数エンジン・クラス・テンプレートをインスタンス化したものです。以下の型は、<oneapi/dpl/random> ヘッダーの oneapi::dpl:: 名前空間で定義されています。

種類 説明
minstd_rand0 oneapi::dpl::linear_congruential_engine<:uint32_t, 16807, 0, 2147483647>
minstd_rand oneapi::dpl::linear_congruential_engine<:uint32_t, 48271, 0, 2147483647>
ranlux24_base oneapi::dpl::subtract_with_carry_engine<:uint32_t, 24, 10, 24>
ranlux48_base oneapi::dpl::subtract_with_carry_engine<:uint64_t, 48, 5, 12>
ranlux24 oneapi::dpl::discard_block_engine<ranlux24_base, 223, 23>
ranlux48 oneapi::dpl::discard_block_engine<ranlux48_base, 389, 11>

以下に示すエンジンは、乱数ベクトルを効率良く生成することができます。これらの型は、<oneapi/dpl/random> ヘッダーの oneapi::dpl:: 名前空間で定義されています。

種類 説明
template<std::int32_t N> minstd_rand0_vec<N> oneapi::dpl::linear_congruential_engine<sycl::vec<std::uint32_t, N>, 16807, 0, 2147483647> minstd_rand0 (ベクトル生成の場合)
template<std::int32_t N> minstd_rand_vec<N> oneapi::dpl::linear_congruential_engine<sycl::vec<std::uint32_t, N>, 48271, 0, 2147483647> minstd_rand (ベクトル生成の場合)
template<std::int32_t N> ranlux24_base_vec<N> oneapi::dpl::subtract_with_carry_engine<sycl::vec<std::uint32_t, N>, 24, 10, 24> ranlux24_base (ベクトル生成の場合)
template<std::int32_t N> ranlux48_base_vec<N> oneapi::dpl::subtract_with_carry_engine<sycl::vec<std::uint64_t, N>, 48, 5, 12> ranlux48_base (ベクトル生成の場合)
template<std::int32_t N> ranlux24_vec<N> oneapi::dpl::discard_block_engine<ranlux24_base_vec<N>, 223, 23> ranlux24 (ベクトル生成の場合)
template<std::int32_t N> ranlux48_vec<N> oneapi::dpl::discard_block_engine<ranlux48_base_vec<N>, 389, 11> ranlux48 (ベクトル生成の場合)

乱数分布

乱数分布は、乱数エンジンの出力が定義された統計的確率密度関数に従って分布するように処理します。これらの型は、<oneapi/dpl/random> ヘッダーの oneapi::dpl:: 名前空間で定義されています。

分布 説明
uniform_int_distribution

範囲内に均等に分布された整数値を生成します。

uniform_real_distribution

範囲内に均等に分布された実数値を生成します。

normal_distribution

正規分布 (ガウス分布) に従って実数値を生成します。

インテル® oneDPL 乱数生成機能の使用モデル

乱数生成は、DPC++ のデバイスコードとホストコードの両方で利用できます。次に例を示します。

#include <iostream>
#include <vector>
#include <CL/sycl.hpp>
#include <oneapi/dpl/random>

int main() {
    sycl::queue queue(sycl::default_selector{});

    std::int64_t nsamples = 100;
    std::uint32_t seed = 777;
    std::vector<float> x(nsamples);
    {
        sycl::buffer<float, 1> x_buf(x.data(), sycl::range<1>(x.size()));

        queue.submit([&] (sycl::handler &cgh) {

            auto x_acc =
            x_buf.template get_access<sycl::access::mode::write>(cgh);

            cgh.parallel_for<class count_kernel>(sycl::range<1>(nsamples),
                [=](sycl::item<1> idx) {
                std::uint64_t offset = idx.get_linear_id();

                // minstd_rand エンジンを作成
                oneapi::dpl::minstd_rand engine(seed, offset);

                // float 型の uniform_real_distribution 分布を作成
                oneapi::dpl::uniform_real_distribution<float> distr;

                // float 型の乱数を生成
                auto res = distr(engine);

                // 結果を x_acc にストア
                x_acc[idx] = res;
            });
        });
    }

    std::cout << "\nFirst 5 samples of minstd_rand with scalar generation" << std::endl;
    for(int i = 0; i < 5; i++) {
        std::cout << x.begin()[i] << std::endl;
    }

    std::cout << "\nLast 5 samples of minstd_rand with scalar generation" << std::endl;
    for(int i = 0; i < 5; i++) {
        std::cout << x.rbegin()[i] << std::endl;
    }
    return 0;
}