2017-11-08 13 views
4

GEOSのC APIを使用して並列シミュレータのジオメトリを管理しています。オブジェクトが制約された領域内に収まるようにする必要があります。 私のオブジェクトがステップを踏むと、その前と現在の位置の間のlineが環境の境界と交差するかどうかを確認します(environment_manager_->get_border()、これはconst GEOSPreparedGeometry*を返します)。Geosとの交差を並列でテストするときのSegfault

コードはいくつかのOpenMPスレッドと並列に実行されています。シミュレーションを開始する前にGEOSを初期化しました。

initGEOS_r(notice, log_and_exit); 
context_handler_ = GEOS_init_r(); 

すべてのスレッドに対してハンドラが1つしかありません。 シミュレーションをいくつかのスレッドで実行すると、GEOSPreparedIntersects_rをクリティカルセクションにラップしないと、コードがenv_intersectの中でsegfaultでクラッシュします。

bool SpaceManager::env_intersect(const GEOSGeometry * line) const 
{ 
    bool intersect; 
    // #pragma omp critical // adding prevents segfault 
    // { 
     intersect = GEOSPreparedIntersects_r(
      context_handler_, environment_manager_->get_border(), line); 
    // } 
    return intersect; 
} 

私が間違っていることを誰かが指摘できますか? OpenMPで動作するためには、GEOSを初期化する必要がありますか? environment_manager_unique_ptrですか?それらのどれも?セグメンテーション違反の


バックトレースを提供します:

Thread 19 "python" received signal SIGSEGV, Segmentation fault. 
[Switching to Thread 0x7fffd63da700 (LWP 4374)] 
0x00007ffff78816b2 in tcache_get() from /usr/lib/libc.so.6 
(gdb) bt 
#0 0x00007ffff78816b2 in tcache_get() at /usr/lib/libc.so.6 
#1 0x00007ffff5dbf0a9 in operator new(unsigned long) ([email protected]=32) 
    at /build/gcc-multilib/src/gcc/libstdc++-v3/libsupc++/new_op.cc:50 
#2 0x00007fffc8468273 in geos::geom::LineString::computeEnvelopeInternal() const (this=0x555555f10170) at LineString.cpp:278 
#3 0x00007fffc845b95f in geos::geom::Geometry::getEnvelopeInternal() const (this=0x555555f10180) at Geometry.cpp:276 
#4 0x00007fffc84612ad in geos::geom::GeometryCollection::computeEnvelopeInternal() const (this=0x555555f15980) at GeometryCollection.cpp:257 
#5 0x00007fffc845b95f in geos::geom::Geometry::getEnvelopeInternal() const (this=0x555555f15998) at Geometry.cpp:276 
#6 0x00007ffff53cea66 in geos::geom::prep::BasicPreparedGeometry::envelopesIntersect(geos::geom::Geometry const*) const() at /usr/lib/libgeos-3.6.2.so 
#7 0x00007ffff53cef82 in geos::geom::prep::PreparedLineString::intersects(geos::geom::Geometry const*) const() at /usr/lib/libgeos-3.6.2.so 
#8 0x00007ffff5907380 in GEOSPreparedIntersects_r() 
    at /usr/lib/libgeos_c.so.1 
#9 0x00007ffff61d7938 in growth::SpaceManager::env_intersect(GEOSGeom_t const*) const (this=0x555555fb3b78, line=0x7fff7c045c20) 

[EDIT]は、OMPスレッドごとに環境の1つのconst GEOSPreparedGeometry*コピーを作成し、スレッドだけ特定のコピーにアクセスして、正常にセグメンテーションフォルトを防止しますcriticalセクションが存在しません。コードは次のようになる。

intersect = GEOSPreparedIntersects_r(
     context_handler_, environment_manager_->get_border(omp_id), line); 

ここenvironment_manager_->get_border(omp_id)戻るスレッド固有const GEOSPreparedGeometry*。これは、以前に単一のポインタを使用していたときに共有データへの同時アクセスの問題が発生したことを意味します。関数がスレッドセーフであると思われるので、これは奇妙です...

+0

なぜあなたは何か間違っていると思いますか?クイック検索では、スレッドセーフが検出された場合はドキュメントを見つけることができませんでした。 unique_ptrはリリースビルドで最適化する必要があります。問題の原因ではありません。 – lars

+0

私は正しく[その投稿](https://trac.osgeo.org/geos/wiki/RFC3)を理解していれば、すべての '' _r''関数はスレッドセーフであると考えられますが、おそらく私はそれらを使用していません正しい方法は... – Silmathoron

+0

クラッシュは 'operator new'の内部で起こります。これは通常、メモリが上書きされたことを意味します(つまり、一部のオブジェクトや配列に対する割り当てられた範囲外のアクセス、または削除されたオブジェクトへの書き込み)。 – 1201ProgramAlarm

答えて

0

明らかにスレッドセーフな実装はまだ準備ができていません(mailing list exchange参照)。 私はこの問題を、各スレッドでグローバル環境ジオメトリのコピーを使用して解決しました(これは明らかに完全な同時テストを可能にします)。