7/21 (火)
ニコニコ動画のプレミアム登録をしてみる
転送速度の改善を期待してニコニコ動画のプレミアム会員に登録してみたが、 転送でエラーが出る率が大幅に減ったよ \(^_^)/
月額 525 円は定期的に引き落とされるので、 止める時は解約を忘れないようにしないと。 ここにメモしておく。
7/11 (土)
[Prog] std::map の lower_bound/upper_bound は直感に反するネーミングだよね
C++ STL の map は lower_bound と upper_bound というメンバを持っている。 「lower_bound(key) は key 以上となる最初のイテレータを指す」というのはいいのだが、 「upper_bound(key) は key を越える最初のイテレータを指す」というのはしっくりこないよね。
数学で言うところの upper and lower bound から、 least upper bounds (supremum) とか greatest lower bounds (infimum) が返ってくるのを期待してしまうよ。
std::map の型を Map とすると、 以下のように書けば key 値以下となる最後の要素を返すことは可能。
Map::iterator least_upper_bound(Map& m, Map::key_type key) { Map::iterator it; it = m.upper_bound(key); if ((*it).first == key) { return it; } else { return --it; } }
7/3 (金)
[CPU] mfence 命令が遅い
IA-32 系のメモリフェンス命令である mfence は実行速度を落とす要因になるようだ。
Pentium4 系 CPU で計測した場合、mfence 命令の実行レイテンシは 130 サイクル程度かかるようだ。 lfence 命令と sfence 命令もそれぞれ 50 サイクル強、50 サイクル弱かかる。
その上、mfence の遅さは実行レイテンシだけではないらしい。 cmpxchg 命令や LOCK 付きのアトミック操作も 80-100 サイクル程度かかるので 単体の実行レイテンシは同程度なのだが、 メモリフェンスはロード・ストアバッファの内容を単に順序化するというよりは 先行するメモリアクセスが全部完了するのを待っているような気がする。
下のようなプログラムの 2: の位置に xchg 命令を置いた場合、 全体の実行時間の伸びは xchg 命令の実行レイテンシ(90サイクルぐらい)にだいたい一致する。 しかし 2: に mfence を置いた場合はプログラム全体の実行時間の伸びは、 1: と 3: にどのようなメモリアクセスを置くかによって変わってきて、 mfence 命令の実行レイテンシ(130サイクル) + αになる。 キャッシュにあたる範囲ではαは +20 サイクル程度になるようで、 mfence 命令一つで 150 サイクルになる。
1: memory-access1 2: memory-fence or atomic-operation 3: memory-access2
実際、SUN の JavaVM の実装だと mfence 命令は遅いので xchg 命令を適当なメモリ位置に発行することで前後の命令の順序化の代替をしているようだ (MFENCE v.s. LOCK addl)。 ただ mfence 命令が先行するメモリアクセスが他の CPU から見えるようになることを保証してくれるのに対して、 xchg 命令などはその CPU の中でのメモリアクセスを順序化しているだけなので効果が多少違う。
問題は今書いているプログラムで mfence の効果が要るかどうかだ。 IA-64 のメモリフェンス命令 mf は仕様書からは、 x86-64 の xchg 命令と同様の効果しか持たないように読める。 IA-64 版は mf 命令で OK だったのだから、mfence 命令は不要な気がしてきた。