TBB::concurrentなコンテナの内容の重複って…

粒子法に限らず、分子動力学計算とかでもそうだと思うのだが、カットオフ距離で空間分割を行って、周囲粒子探索を効率化するという話はもちろんなのだが、それ以外に、相互作用の計算は、2粒子間のペアごとに計算していくわけなのであるから、2つの粒子の間に働く力は一回だけ計算し、その計算結果は2粒子でシェアするように計算処理を作らないと、それぞれの粒子について、同じ計算を2回してしまうことになるだろうから注意が必要な気がした。
つまり、相互作用する粒子ペアのリストをまず作成しておき、実際の相互作用計算は最後にまとめて一括に行うという方法がよいだろう。その方が計算回数も減るし、まとまった処理を一気にやるという意味で、コンピュータにもやさしいのではないだろうか。
そうなってくると、相互作用粒子ペアのリストをいかに効率よく作るかということが、肝要になってくる。TBBを用いた並列化計算では、tbb::concurrent_vector などが、まずペアの入れ物として必要だろう。各粒子に、周囲相互作用粒子のリストを持たせれば、既知相互作用の重複登録を防ぐことはできるだろうが、メモリも食うだろうし、あまり速くはなさそうだ。それよりかはconcurrent_vector などに全相互作用を登録しておいて、重複を取り除く方法がベストのような気もする。sort, unique やeraseといったstlアルゴリズムは、concurrent_vectorに適用できるのだろうか。
と思ってやってみると、std::sortとstd::unique はコンパイル通るようたが、erase がないようだ。んんー、しかしそれは致命的だよなあ。insert() とerase() がないのが玉にキズだとインテルのページにも書いてある。。
重複を取り除くのは、むしろconcurrent_hash_map() とか使えばいいのだろうか。なんかあまり速くなさそうな気すらしてきたぞ。
なのでもしかしたら相互作用ペアリストはシングルスレッドで作っておいて、最後の相互作用計算はパラレルでやればいいのかも知れない。あるいは並列化できるのだったら、始めから相互作用リストなんて作らずに、同じ相互作用の重複計算も並列化に任せきって、各粒子ごとに相互作用和を計算してった方が速いかも知れない。なんかあまり夢のない結論な予感になってしまった。。
ていうか結局TBB::concurrentなコンテナの内容の重複ってどうやって取り除けるんだ??

後日記:
というわけで、2粒子間の相互作用は1回だけ計算するように作ってみたのだが、結論から言うと、ろくなことがなかった。

  • メインループが最低でも2つになってしまう。(粒子ペア探索と、相互作用計算)⇒これだけで並列化への見通しがよくないことに気付く。
  • 本来2回計算してしまいそうなものを1回しか計算しないようにするのはそれ自体コストの高い処理だ。粒子間相互作用の計算コストとの兼ね合いにもよるが、今回の自分の場合は、大きなループで回して、バカ正直に粒子間相互作用を2回重複して計算せざるを得ない当初のシンプルな方式の処理速度が一番高速だった。シングルスレッド処理での話だが、並列化を考える上でもこっちのシンプルな方式の方が断然将来性が高い気がする。