Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How Are Random Numbers Generated ?

How Are Random Numbers Generated ?

Go の math/rand パッケージの実装を深ぼっていく。math/rand を最適化する実装も見ていく

発表イベント
https://andpad.connpass.com/event/243953/

Kenta Takahashi

May 11, 2022
Tweet

More Decks by Kenta Takahashi

Other Decks in Programming

Transcript

  1. How Are Random Numbers Generated ? \⾮公式/ Go Conference 2022

    Spring スポンサー企業4社 アフタートーク Showcase Gig
  2. Who am I ? ⾼橋 建太 株式会社 Showcase Gig 所属

    Showcase Gig の Platformチームで主に認証認可 部分を担当。主にバックエンドエンジニアとして マイクロサービス認証認可の設計や開発をリード。 好きな⾔語は Go。毎週、社内で Go の勉強会を主 催して⾏い、社内 Gopher 計画を遂⾏している。 なんと次回50回目!!
  3. Agenda • 前提知識 • Random Numbers (乱数) • Pseudo random

    number(疑似乱数) • math/rand package • crypto/rand package • benchmark
  4. Random Number (乱数) • ランダムに選ばれた値のこと • 乱数を数列として表したものを乱数列という • e.g) <x1>

    = 6,3,26,8,33… • 性質 • Randomness (無作為性) • 統計的な偏りがない • Unpredictability (予測不可能性) • 過去の乱数列から次の数が予測できないこと • Irreproducibility (再現不可能性) • 同じ乱数を再現できないこと
  5. Pseudo-Random Number (疑似乱数) • Seed を入力して決められた手続き (アルゴリズム) に従って生成 される乱数のこと •

    同じ、Seed だと同じ結果になる • 疑似乱数を生成するアルゴリズムを疑似乱数生成器という • Pseudo-random number generator: PRNG と表記することが多い • 大きく2つに分けられる • Randomness のみ • Randomness + Unpredictability
  6. Pseudo-Random Number (疑似乱数) • Seed を入力して決められた手続き (アルゴリズム) に従って生成 される乱数のこと •

    同じ、Seed だと同じ結果になる • 疑似乱数を生成するアルゴリズムを疑似乱数生成器という • Pseudo-random number generator: PRNG と表記することが多い • 大きく2つに分けられる • Randomness のみ • Randomness + Unpredictability 再現性がある
  7. Pseudo-Random Number (疑似乱数) • Seed を入力して決められた手続き (アルゴリズム) に従って生成 される乱数のこと •

    疑似乱数を生成するアルゴリズムを疑似乱数生成器という • Pseudo-random number generator: PRNG と表記することが多い • 大きく2つに分けられる • Randomness のみ -----------------------------> math/rand • Randomness + Unpredictability ------------> crpto/rand (コストがかかる) あくまで自分のイメージ ですが、このように捉え ています!
  8. math/rand package について • pseudo-random number generator (PRNG) が Go

    に実装されている • 無作為性はある • 予測不可能性はない func main() { for i := 0; i < 5; i++ { println(rand.Intn(100)) } } https://go.dev/play/p/TMGkMVV9zt3 81 87 47 59 81 Program exited.
  9. math/rand package • 解説 • PRNG は、Go に実装されているのでどの環境で実行しても全く同じになる • 何度実行しても同じ結果になる

    • 同じ Seed が使われている -> PRNG の性質 • https://cs.opensource.google/go/go/+/refs/tags/go1.18.1:src/math/rand/rng.go;l=24 • 不規則に値が出力されている -> 実行中に状態を保持してシードを変えている • 予測不可能性が満たされていない -> seed がわかる func main() { for i := 0; i < 5; i++ { println(rand.Intn(100)) } } https://go.dev/play/p/TMGkMVV9zt3 81 87 47 59 81 Program exited.
  10. math/rand package • Seed は外部からも渡せる • 以下の例だと同じシードだと同じ結果がでるということを表しています • rand.Seed(time.Now().UnixNano()) •

    よくあるパターンだと nanosecond を渡して疑似乱数を生成する • nanosecond 自体は規則性があるため 安全ではない • 安全な seed が渡せない -> crypto/rand を使うしかない func main() { for i := 0; i < 5; i++ { rand.Seed(2) println(rand.Intn(100)) } } https://go.dev/play/p/HqR_T6Qy7zU 86 86 86 86 86 Program exited.
  11. どうやって seed を渡しているのか? func main() { for i := 0;

    i < 5; i++ { println(rand.Intn(100)) } } https://go.dev/play/p/TMGkMVV9zt3 81 87 47 59 81 Program exited.
  12. lockedSource • 構造体の中に sync.Mutex がある • Groutine セーフにできている • rngSource

    中では、疑似乱数生成の ロジックが実装されている • https://go.dev/src/math/rand/rand.go
  13. lockedSource でパフォーマンス改善 • lockedSource をなくすとロックフリーで実行できる • math/rand.New でローカル変数に PRNG を初期化することができる

    • NewSrouce 渡たすだけ • 並列に実行される予定はなく、単にパフォーマンスがほしいとき に有効 https://go.dev/play/p/aQk1XjRYONI
  14. crypto/rand package について • Package 内に以下の記載がある https://pkg.go.dev/crypto/rand On Linux and

    FreeBSD, Reader uses getrandom(2) if available, /dev/urandom otherwise. On OpenBSD, Reader uses getentropy(2). On other Unix-like systems, Reader reads from /dev/urandom. On Windows systems, Reader uses the CryptGenRandom API. On Wasm, Reader uses the Web Crypto API. • つまり、OS によっていろんな 生成器を使い分けている • 安全な PRNG なので安心
  15. Benchmark… BenchmarkMathRandNoLock-8 212501983 5.725 ns/op 0 B/op 0 allocs/op BenchmarkMathRand-8

    73510988 16.09 ns/op 0 B/op 0 allocs/op BenchmarkCryptoRand-8 1205656 995.8 ns/op 56 B/op 4 allocs/op • Non Lock が一番パフォーマンスがいい • ロック有りだと 3 倍ほどパフォーマンスが悪い • それ以上に crypt/rand が一番悪くて、一番目と 200 倍くらいあ る