memologue RSSフィード

書いている人

日記というよりは備忘録、ソフトウェア技術者の不定期メモ。あるいはバッドノウハウ集。プライベートで調査した細々した諸々のスナップショット。嘘が散りばめられています。ISO/IEC 14882(C++)とPOSIX, GCC, glibc, ELFの話ばかりで、WindowsやMacの話はありません。特に記載がなければLinux/x86とILP32が前提です。時間の経過と共に古い記事は埋もれてしまいます。検索エンジンから飛んできた場合は、ページ内検索をご利用いただくかgoogleキャッシュを閲覧してみてください。技術的な記事を書きためる場所として使っています。言及してもらえると喜びます。主要な記事の一覧を書いておきます:

にんきコンテンツ: [GCC] mainを一度も呼ばないばかりか蹂躙する / Binary2.0 Conference 2006 発表資料 / C++ で SICP / ついカッとなって実行バイナリにパッチ / hogetrace - 関数コールトレーサ

昔のPOSIX関係の記事: シグナルの送受に依存しない設計にしよう / シグナルハンドラで行ってよい処理を知ろう / マルチスレッドのプログラムでのforkはやめよう / スレッドの「非同期キャンセル」を行わない設計にしよう / スレッドの「遅延キャンセル」も出来る限り避けて通ろう / マルチスレッドプログラミングの「常識」を守ろう / C++でsynchronized methodを書くのは難しい / シグナルハンドラからのforkするのは安全か? / g++ の -fthreadsafe-statics ってオプション知ってます? / 非同期シグナルとanti-pattern / localtimeやstrtokは本当にスレッドセーフにできないのか / UNIXの規格について / マルチスレッドと共有変数 - volatile?なにそれ。 / type punning と strict aliasing / アセンブラで遊ぶ時に便利なgdb設定 / 最近の記事は一覧から

2004-10-11

[] Singleton速度比較 (1)

2chのマルチスレッドスレッドで興味深い議論があった。見ていただければわかるが、「C++でdouble checked locking(DCL)は安全か」という話題を、CPU毎に検討している。各CPUのmemory modelの話に立ち入った、楽しい議論だ。特に、リンクされている

Double-Checked Locking, Threads, Compiler Optimizations, and More
http://www.nwcpp.org/Downloads/2004/DCLP_notes.pdf

なるScott Mayersさんのペーパーがイケてると思う。最近書かれたばっかり。ここを読んでいなかったら当分知ることはなかっただろうな。ラッキー。


というわけで本題も興味深いのだが、とりあえずスレッドの中でいくつか示された「DCLに代わる高速なシングルトンの実装方法」が実際どの程度高速か興味がわいたので計測してみた。次の5種類を試した。


SynchronizedSingleton:
インスタンス取得メソッド全体をmutexで囲み、完全同期化を行ったシングルトン。
DCLSingleton:
インスタンス取得メソッドに Double Checked Locking Pattern を用いたシングルトン。
OnceSingleton:
インスタンス取得メソッド中でのインスタンスのnew処理を、pthread_onceで一度
だけ行うようにしたシングルトン。

> もしくは、pthread_once(3)のようなシステムが用意してくれてるAPIを使うとか。
> DCLが有効なアーキテクチャではpthread_once()の内部でDCLを使ってるかもしれ
> んが、使う側からはそういう内部実装を一切気にしなくて良い。
GccTSDSingleton:
インスタンス取得メソッドはSynchronizedSingletonと同一だが、それをTSDでキャッ
シュするように細工したシングルトン。

TSDは、__thread というGCC拡張のキーワードを用いて確保する。

> 正確に言うと、某CPUが数発のマシンでDCLを(バリアなしで)使ってる人に、バリア
> 使うか858のように書き直せと言いたいんです。そのための調査をしていまして。
> 自分はどちらかというと858派ですと付け加えておきます。基本的にはパフォーマンス
> より安全・確実な方を選びたいですね。
> # 完全synchronizeのペナルティがイヤならTLSにでもポインタいれとけばぁ?と思う。
TSDSingleton:
インスタンス取得メソッドはSynchronizedSingletonと同一だが、それをTSDでキャッ
シュするように細工したシングルトン。

TSDは、POSIXのAPIを用いて確保する。

なお、DCLの実装はx86向けのもの*1である。各CPU向けにどのようなメモリバリアを記述すればよいのかは、glibc(LinuxThreads)のpthread_onceの実装*2を参考にした。より正確には、各アーキテクチャ向けに linuxthreads/sysdeps/アーキテクチャ/pt-machine.h や linuxthread/internals.h で定義される、MEMORY_BARRIER(), READ_MEMORY_BARRIER(), WRITE_MEMORY_BARRIER() マクロを参考にした。参考までに、このマクロのx86の場合の#define内容は次の通りである。


[internals.h]

/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the
   architecture doesn't need a memory barrier instruction (e.g. Intel
   x86).  Still we need the compiler to respect the barrier and emit
   all outstanding operations which modify memory.  Some architectures
   distinguish between full, read and write barriers.  */

#ifndef MEMORY_BARRIER
#define MEMORY_BARRIER() asm ("" : : : "memory")
#endif
#ifndef READ_MEMORY_BARRIER
#define READ_MEMORY_BARRIER() MEMORY_BARRIER()
#endif
#ifndef WRITE_MEMORY_BARRIER
#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER()
#endif

また、TSDSingletoがOnceSingletonよりも低速になるのは下のほうに貼ったソースコードを見れば自明だが、一応実験しておいた。


測定環境は、Linux 2.6.8(FC3test2), glibc-2.3.3(NPTL), g++-3.4.2, boost-1.13.0, Pentium4-2.8GHz(HT) である。


→ 続き

→ 関連記事: C++でsynchronized methodを書くのは難しい (1) /  g++ の -fthreadsafe-statics ってオプション知ってます?

*1:コンパイラによるreorderだけを防止している

*2:glibc-2.3.3-200405070341/linuxthreads/mutex.c

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/yupo5656/20041011/p1