2013年12月16日

最近のCPUでは乱数生成がはやい話

Ivy Bridge以降のCPUではCPU内に乱数生成器が含まれています。それに対応した最近のrngdをつかうとそれなりに乱数生成が速くてしあわせになれます。

linuxでは乱数を取得するために /dev/random と /dev/urandom の2種類のデバイスがあります。それぞれの説明は man 4 random にみっちり書いてありますが、かいつまんで言うと:
  • random: カーネルがあつめてきたノイズを元に品質の高い疑似乱数を生成します。ノイズが不足するとblockします。
  • urandom: カーネルがあつめてきたノイズを元にそこそこの品質の疑似乱数を生成します。品質はそこそこですがblockしないので速いです。
ためしにcat /dev/random とかすると1kとか4kくらい乱数が出力されて止まってしまう。これでは割と足りないので選択肢が2種類。1) 品質をあきらめてurandomを使う、2) 乱数生成器をつけてrngd経由で書き込みとエントロピーの追加をおこなう。乱数生成器は一部のチップセットに内蔵されたりしてたんですが、 専用ハードウェアもあったりします。

いいかげんな乱数でよければurandomなのですが、sshのキーをつくるとかsslちゃんとやろうとか証明書発行しようとかしたいときは/dev/randomをつかいたい、でも周辺装置とかチップセットの制約とかめんどいなー。 という事情がありました。

そこでIvy Bridge世代ではrdrand命令を追加して、CPUのチップ内で乱数生成をして専用命令で読みだせるようにしました。このテクノロジー自体もかなりおもしろいです。IEEE Spectrumの記事がおすすめ。


実際つかってみましょう。rngdの最近のバージョンでは、rdrand命令に対応しています。最近のfedoraであればデフォルトでrngdが動いていますが、有効でなければ systemctl start rngd.service とか叩いて有効にします。

ddで1バイトずつ乱数読みだしをおこないます。乱数生成器がない環境とかrngd止まってるとかだとこれがblockしてずーーっと待つことになるので注意。
$ dd if=/dev/random of=/dev/null bs=1 count=1000000 
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB) copied, 4.32184 s, 231 kB/s
 比較対象としてurandomでも同じことをしてみましょう。
$ dd if=/dev/urandom of=/dev/null bs=1 count=1000000
1000000+0 records in
1000000+0 records out
1000000 bytes (1.0 MB) copied, 1.3472 s, 742 kB/s
urandomのほうがまだ速いですけど1/3くらいの速度はでますね。これくらい出てくれるなら乱数つかい放題といってもいいんじゃないかしら。


2013-12-16追記
Debianではrng-toolsが独自forkなためrdrand対応がまだ入っていないらしい。rng-toolsのアップデートについてのケースがfileされている。一方UbuntuにはDebianはforkだから独自に新版入れてくれというケースが。Debianの動き悪いのはわかるけどUbuntuだけ対応するってなんだかなあ。

RHEL 5 ELS inclusion listでてた

Red Hat Enterprise Linux 5 ELS Inclusion List https://access.redhat.com/articles/2901071  が公開されてた。 なかなか範囲が狭くて厳しい。あとインターネットに直接晒されるようなプログラムがの...