Segfault当与geos并行测试交叉点时

我使用GEOS的C API在并行模拟器中管理几何:我需要确保对象保留在受限区域内。 为此,当我的对象做出一个步骤时,我检查它之前和当前位置之间的line是否与环境边界相交( environment_manager_->get_border() ,它返回一个const GEOSPreparedGeometry* )。

代码与多个OpenMP线程并行运行。 在开始模拟之前,我初始化了GEOS

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

所以我只有一个处理程序的所有线程。 当使用多个线程运行模拟时,如果我没有将GEOSPreparedIntersects_r在关键部分中,代码会在env_intersect内发生segfault GEOSPreparedIntersects_r

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;
}

有人能指点我做错了什么吗? GEOS的初始化需要与OpenMP一起工作吗? 它是否来自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) (sz=sz@entry=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)

[编辑]为每个OMP线程创建一个const GEOSPreparedGeometry*环境副本并仅成功访问线程特定的副本,从而防止缺少critical部分时的段错误。 代码变为:

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

其中environment_manager_->get_border(omp_id)返回线程特定的const GEOSPreparedGeometry* 。 这意味着当我以前使用单个指针时,问题来自对共享数据的并发访问。 这似乎很奇怪,因为函数应该是线程安全的...


显然线程安全的实现尚未准备就绪(请参阅邮件列表交换)。 我通过在每个线程上使用全局环境几何体的副本来解决这个问题(这显然也允许完全并发的测试)。

链接地址: http://www.djcxy.com/p/79267.html

上一篇: Segfault when testing the intersection with geos in parallel

下一篇: How to safely parallel the for