IvyBridgeとは仲良くできるか
IvyBridgeが発売されてからこうそれなりに時間が経ちまして、僕がIvyBridge搭載のMacBook Pro Retinaを購入してからしばらく経ったりしたんですけども。
このRetinaちゃんの文字が綺麗すぎてコーディングがはかどると思いきや、JISキーボードなのでその辺は微妙なところだったりするのが何ともはや。そんな感じの毎日を過ごしつつ。
本日は、IvyBridgeに搭載されているRDRAND命令についていろいろ調べてみたんでそれを書いてみます。
例によって微妙にちゃんと調べていないので、ご指摘ください。
しかもこれ、実は八月の頭にやったネタなので、それもあわせてご了承ください
あーもうはてな記法全く思い出せない。カンペください。
RDRAND命令とは?
IvyBridgeに搭載されたハードウェア乱数生成器です。以上
詳細は
http://software.intel.com/sites/default/files/m/d/4/1/d/8/441_Intel_R__DRNG_Software_Implementation_Guide_final_Aug7.pdf
にあるので、これを読んだ方がいいと思います多分。
つかいかた
GCC4.7系にはRDRAND命令をマップしたIntrinsicsが追加されているので、それを使うのが最もてっとりばやいでしょう
もちろん、アセンブリで表記することも可能です
インラインアセンブリで表記するとこんな感じ
unsigned int rand; __asm__(“rdrand %0” : “=r(rand)”);
Intrinsicsを使用して書くとこんな感じ
#include <immintrin.h> int main() { unsigned int rand; _rdrand32_step(&rand); return 0; }
Intrinsicsを使う場合には、gccのコンパイルオプションに-mrdrndスイッチをつける必要があります。
コンパイルするときは次の感じ、ってことですね
$ gcc main.c -mrdrnd
種類
RDRAND命令には、3つの乱数生成命令があります
int _rdrand16_step(unsigned short* dst) int _rdrand32_step(unsigned int* dst) int _rdrand64_step(unsigned long long* dst)
それぞれ、16bit,32bit,64bitとなるわけですね。わー
リターンは、0が失敗、1が成功の意です
ぱふぉーまんす
じゃあ実際のところ、ハードウェア乱数生成器ならパフォーマンスはどうなの?というのがやっぱり気になるところだと思います
僕も気になるので、そこらへんはかってみました
環境は次の通りです
C言語標準のrand()関数との比較コードを書きました
const size_t num = 1000000; std::vector<unsigned int> rdrand_result(num); std::vector<unsigned int> rand_result(num); double rdrand_start = gettimeofday_sec(); for(size_t i = 0; i < num;++i) { _rdrand32_step(&rnd[i]); } double rdrand_end = gettimeofday_sec(); double rand_start = gettimeofday_sec(); for(size_t i = 0; I < num;++i) { rand_resul[i] = rand(); } double rand_end = gettimeofday_sec();
結果は次のようになりました
rdrand: 0.0512741 sec. rand: 0.0116398 sec.
はい、完敗ですね。お疲れさまでした。
しかもこれ最適化オプションかけてないんですよ。死ぬしかない
……何が悪かったんだろうとか悲しいことを思う前に、rand()関数がどうしてこんなに速いのかを確認してみます
rand()関数の実装は、僕の知る限りではmodなのですが(誰か違ったら教えてください)、modってそもそも超速くね?とか思う訳です
書いてる途中から薄々そんな気はしてましたが
と、ここはまだ詳細検証中なのでうかつには書きません。間違えてそうだし。
はぁ、なんか悲しくなってきたのでこの辺で筆を止めます。
突っ込み募集中なので、よければ指摘してください。つーかこのルーターネットワークがぶちぶち切れすぎて笑えないのだ……