shared_ptr の排他制御を抑止する。

スマートポインタ boost::shared_ptr は非常に便利であり、おそらく Boost C++ Libraries の中でもっとも多く使われている機能のひとつです。boost::shared_ptr は、普通は何も考えずにデフォルトのまま使っていても問題はないのですが、いざ効率のことを考え始めると、問題点が浮き上がってきます。

shared_ptr はスレッドセーフな設計がされており、参照カウンタの増減の際は当然排他制御が行われます。排他制御を行うかどうかは、Boost.Config で決定するわけですが、Visual C++ 2005 のようにシングルスレッドをサポートしない処理系では、常に排他制御が行われることになります。

しかし、現実には、シングルスレッドで十分なアプリケーションも多数ありますし、仮にマルチスレッドであったとしても、shared_ptr をスレッド間で共有する箇所はごく限られているはずです。だとすれば、shared_ptr の排他制御は、多くの場合、単なるオーバーヘッドと化してしまいます。

Boost C++ Libraries 1.33.0 以降では、BOOST_SP_DISABLE_THREADS マクロを事前定義することにより、shared_ptr の排他制御を抑止できるようになりました。ほとんどのアプリケーションでは、このマクロを問答無用で付けても問題ないでしょう。

BOOST_SP_DISABLE_THREADS マクロによって排他制御を抑止した上で、スレッド間で shared_ptr を共有する場合には、当然のことですが、自分でクリティカルセクションを作る必要があります。

Googleで検索三位なのでコメ。 shared_ptrの

Googleで検索三位なのでコメ。
shared_ptrの排他制御は、いくつかのメジャーなプラットフォーム( http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm#Threa... )ではInterlocked系のイントリンシック関数(=実質的にアセンブリ命令)によるロックフリーの非常に高速な実装がされているようなので、ボトルネックで大量にshared_ptrの参照カウントが変化するような特殊なコードでもなければ放置して構わないような気もします。
まぁ、ポインタが示すオブジェクトの変更などをする場合は結局排他が必要になるので、#define BOOST_SP_DISABLE_THREADSをした上で全て自前で面倒を見る方が都合がいい状況も十分にありそうですが。
むしろ、#define BOOST_DISABLE_THREADSでBoostライブラリ全体をシングルスレッド用にしてしまう方がいい、という状況も多そうですね。

コメントありがとうございます。 確かに、ほと

コメントありがとうございます。

確かに、ほとんどのプラットフォームではインラインアセンブラのコードに展開されます。
それでも、バスロックがかかるので、あまり楽観はできない気がします。

shared_ptrのコピーが大量に発生する状況は、コンテナの要素にする場合など、いくつか考えられます。
そんな場合は、ボトルネックを調べるまでもなく、可能であれば排他を切ってもよいかと思います。

> むしろ、#define BOOST_DISABLE_THREADSでBoostライブラリ全体をシングルスレッド用にしてしまう方がいい、という状況も多そうですね。

はい。これは十分に考えられると思います。

_

これは効率というより,
スレッドの扱いの問題ではないでしょうか.

コメントありがとうございます。

> これは効率というより,
> スレッドの扱いの問題ではないでしょうか.

本来の目的はそうですね。

追記:
すみません。誤って元のコメントの一部を消してしまいました。

このエントリーを含むはてなブックマーク