New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
擬似乱数のシード生成方法の推奨に、一貫性がない #451
Comments
シード値について別ページにしてしまうべきかもしれません。random_deviceが信用できない実装も現実に存在するので・・・ |
@yumetodo さんの また、計算機で扱われる疑似乱数列はセキュリティーに対してのみ使われるのではなく、シード値により疑似乱数列を再現可能である事もシミュレーションへの応用では重要な事もあり、このチケットの関連する記事の編集時にはセキュリティーに偏重した記事になりすぎないように編集者には注意して頂ければ幸いです。 加えて、別ページでセキュリティーについて特に記述する際は暗号論的擬似乱数についての解説と |
それは初耳でした・・・、ちなみに参考ページなどありますか? |
MT が暗号論的に安全ではないことは松本眞先生の HP にも記載されています:
|
あ、すいません。ぼくが書いたセキュリティ用途というのは、暗号論的という意図ではないです。 シード生成の話を個別ページに書くなら、リファレンスから外れる場合はarticle階層に記事として書くのがよいと思います。 |
|
私もmingwのあれだけですね |
「セキュリティ用途」というのは語弊があるのでたとえば「シミュレーション用途」とした方がよいと思います.
ちなみに clang の 他の環境については分かりません. そもそもシミュレーションでシードを指定するのは結果を再現するためや,違うシードでも同じ結果を得られるか確認するためだと思います. |
「セキュリティ」という言葉の代わりに「シミュレーション」という言葉を選択することが適切かは、ちょっと調べる必要がありますね。「再現性」という点についてであれば「シミュレーション」という分野に含まれているので問題ないですが、「ユーザーに(絶対にではないけど)予測されたくない」という用途が「シミュレーション」という分野またはその定義に含まれているのか、あるいはその用途が広く認知されているのか、という根拠が必要になると思います。もしどなたか提示できるのであれば、お願いします。 現在の文章がこれで、
「セキュリティホール」という言葉を使用せずに、以下のような修正ができるでしょう:
|
いや、この際具体的な用途はぼかして、seedとして何を使うかと生成アルゴリズムに何を使うかに分けた上で安全性順に列挙して一つのページで取り上げるべきかと。 ちなみにseedを無駄にいろいろな方法で取得するコードを以前書いたことがあります。 |
まず、シード生成について個別ページを用意することはかまいません。どなたか動機がある人が書いてください(私はとくに動機がないので書きません)。「書くべき」という意見だけでは書かれないので、誰も書かないなら書かないで終わるだけです。 ここでいま議論すべきは、シード生成についての記事を書く・書かないに関わらず、概要ページで書く内容と、一貫性あるデフォルトのシード生成の方針、 ひとまず、 |
以上をふまえると, 擬似乱数生成器のシードに使うのにはいいですが,
に使用するのは推奨されないと思います.
確かに程度問題ですが, あるいは
用途を明記しなくてもいいと思います.
C++ 固有の問題ではないので書かなくてよいと思います. @pegacorn さんの投稿に立ち返ると,
について,乱数列の予測不可能性やセキュリティ強度を高めるのはシードが行うことではない (暗号論的に強い乱数生成法を使うべき) ので, |
いえ、問題を知った上で使用する分には問題ないです。規格上の保証がないということが、実装を理解した上での用途を限定することにはならないです。
workaroundを示したまでです。MinGW環境の
標準ライブラリの範囲内で、正しい選択を促す手助けはあってもよいと思います。ぼくの考えでは、それはリファレンスページに一文書くだけで済むと思うので、記事を起こすほどではないと思いますが。
例として |
とりあえずmingwの実装に対するワークアラウンドはWin32APIの 擬似乱数列生成アルゴリズムに何を利用するかは、各擬似乱数生成クラスの解説ですでにある程度解説されているので問題があれば追記すれば良く、STLのそれが不満であれば同じインターフェースのクラスを自作すればいい、でFAでは。 |
ここで言うworkaroundは、MinGWの |
ところで https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/random.h |
「エポックを乱数のシードにすると,起動時間を調整することでユーザーに悪用される虞がある」 シードについて,
ですが,
とするのはどうでしょうか.(MinGW では
と追加してもいいと思います.
GCC の Implementation Status に書いてありました.
|
@e-kwsm
ref:
はい、そのようですね。 |
「何を指定しても同じ結果となる」というのは任意の文字列を与えても効果はない ということだと思われるが,返す乱数は異なるはずなので語弊がある. 引数の効果については 21bcf38 で書いたので削除した.
* 代替手段として `RDRAND`, `CryptGenRandom`, `RtlGenRandom` を追加
ひとまず 概要 の
について,多分 MSVS のことだと思うのですが,ソースはありますか? 公式資料は見つけられませんでしたが,Stack Overflow には clang 等の |
VCに関しては執筆当時に実装を見て記述しましたが、現在は環境がないのでわからないです。 |
ドキュメントは見つけられませんでしたが、以下の実装を見るとVC++2015/2017でもStack Overflowに記載のVC++2010と同様に
|
正: |
rand_s and CryptGenRandom is a wrapper function of RtlGenRandom. ref: - #451
@pegacorn 修正してみました。規格書を見る限り代入演算子の戻り値の型指定は |
* random_device は rand_s を使用すると明記 * rand_s, RtlGenRandom, CryptGenRandom の説明追加 (MinGW で上記を使えるかは不明)
一通り書きました |
むしろ逆ではないかという印象を受けるのですが(
リリース版 #とは |
開発時にはシードを固定してテストを行うが,リリース版では実行ごとに乱数が変わった方がよい/変わるべき (例えばゲーム) という意味で書きました. |
ありがとうございます
なるほど。ただ何かもうすこし意図が伝わりやすい文言に変えたいですがなにかないかな・・・ |
ゲームでもランダムテストでも、開発中でも乱数列は変わったほうがよいですね。開発中にシードを記録しておくことで、問題が発生したときに記録しておいたシードで問題を再現させる、という運用になると思います。 |
@e-kwsm ※1…C++11のその他の擬似乱数生成器については確認できていません。 |
シードを指定したり,ランダムなシードを使ったりを選べるのは便利ですが,テスト毎にシードが変わると,結果が変わった原因がシードなのかコード修正なのか分かりません. 私は,開発中のテストでシードを固定して以下を検証しています:
違うシードでも同程度の値に収束するかの検証は大事ですが,通常それにはコストがかかる (例えばコインを投げて表が出る確率を計算する場合,投げる回数が少ないと当然値はばらつきます) ので,あまり頻繁にはできません.
「あらゆる」入力 (シードを含む?) に対して検証するのは非現実的なので,問題が発生したシードを使ってデバッグということになるかと思います.
記事では |
@pegacorn さんの書かれた懸念に関しては、以下のように文脈を限定する修正をすればよいのではないでしょうか。
「決定論的」と「非決定的」で書き方が対称になっていないのは意図したものでしょうか。 |
これはランダムテストの文脈でしょうか。 例として、ランダムテストで有名なHaskell言語のQuickCheckライブラリを挙げましょう。このライブラリは他の多くの言語に移植され、広く使われています。 @e-kwsm さんのおっしゃる検証方針もひとつのやり方だとは思いますが、それは個人的なものなのか、あるいは何らかのソフトウェア開発プロセスとして確立しているものでしょうか。
ランダムテストでは実際に、あらゆる入力を検証し、エラーになる値を見つけ出してそれが正しい入力か、受け付けてはならない入力かを判断して、コードをより強固にします。これは現実で実際に行われていることです。 |
書き方が悪かったのですが,「
ランダムテストの文脈ではないです. シードを変えてしまうと,結果が変わった原因がコードの修正なのかシードなのか区別することができません.
「毎回変わるシード」というのは,ランダムな入力を生成するための,プログラム外部のものですか?
個人的な方法なので,もし詳しい方がいれば教えていただけると幸いです. |
意見が衝突していていて二者間では合意に至れない状態になっていると思います。そのため、第三者意見として、私と @e-kwsm さん以外の例が必要となります。第三者意見は、文献 (インターネット上の記事、論文、書籍、オープンソースソフトウェア) などの収集によって得られるでしょう。 しかし、私が示したランダムテストの文脈においては、開発時にシードが変わることが求められます。これは、 @e-kwsm さんが書かれた「リリース版においては、実行ごとに擬似乱数のシードが異なることが求められる。」という文章に対する反論として成立しているように思います。そのため、開発時にもシードを固定せず変動させることが有用であり、リリース版のみに限られたものではないと言えるのではないかと思います。 それとは別に一点質問です。
シードを固定することは、ロジックの維持には有用だと思いますが、リリース版においてシードを変動させて動作することは、開発時に検証しないのでしょうか?開発版で動作するものが、必ずしもリリース版で正しく動作するものではなく、かつ開発時に検証していない動作をリリースしてはならないと思います。
QuickCheckの機能としては、プログラム外部からランダム入力を生成するためのシードです。しかし、入力を生成するのが外部なのか内部なのかは、大きな違いはないと考えています。テスト可能なプログラムを設計するためには、外部から入力を受けることが必要となるためです。たとえば、現在日時に依存したプログラムはテストしにくいため、現在日時をパラメータとしてとるよう設計します。ランダムな入力を受け付けるのも、それと同じです。 |
モンテカルロ・シミュレーション分野での、テクニックとしての記事: ここでは、(オプションとして)固定シードを選択する場合の理由として、以下の2つを挙げています:
この記事は、 @e-kwsm さんのとっている手法が他所にとっても有用であると裏付けるものです。しかし、モンテカルロ・シミュレーションについては開発手法的な記事はなかなか見当たらないですね。 ここは、モンテカルロ・シミュレーションで開発時にシードを変動させることが必要かを調査するよりは、他分野においてそういったことが必要となっているかを調査して反例を示したほうがよさそうな気がします。ランダムテストの分野で私はそれを示したつもりですが、不足であればまた探します。 |
「リリース版においては、実行ごとに擬似乱数のシードが異なることが求められる。」というのは当然の要件だと認識しています.また,この文言は開発中にシードをどうするか (固定するかどうか) を制限するものではありません.
簡単に言うと,私は Monte Carlo 法で多粒子系のシミュレーションをしています.結果が収束するまで時間がかかるので,通常のテストは短めに回して結果が一致するかどうか等を確かめています. 記事ではテスト時のシードをどうするかを書いていませんが,この issue でどうすべきかを決めて書きますか? |
ありがとうございます。 @e-kwsm さんの意図は理解しました。そのうえで、開発時のシードの決め方も、方針を示すくらいはしておこうかと思います。 修正前:
修正後:
「リリース版」という表現をやめて、開発中の検証も考慮するよう修正しました。これを元に議論して、問題なさそうならコミットして終了としましょう。 |
記事に
と書いたのと,「実際に乱雑さが必要となる状況」という表現が分かりにくい (特定のシードを与えることで乱数列に偏りが出ることは通常ない) ので,より簡潔に
とするのが良いと思います. |
それがよさそうですね。対応しておきます。 |
擬似乱数生成器の各テンプレートクラスのコンストラクタの説明ページに記載されているシードの説明と、標準乱数ライブラリの基本的な使い方に書いてあるシードの説明が矛盾しています。
標準乱数ライブラリの基本的な使い方に記載されている通り、現在時刻を使用するのはセキュリティ上問題があるので、標準乱数ライブラリの基本的な使い方の方に合わせた方が良いのではないでしょうか。
The text was updated successfully, but these errors were encountered: