我在应用程序中有两个模块。 Module1 拥有并构建boost::geometry::index::rtree
。 Module2 对 Module1 进行查询,并将其传递给RTree。现在我想加速并拥有几个 Module2 实例,这些实例向一个Module1 实例发出查询,并单独工作。我100%肯定,虽然任何Module2工作RTree都没有改变。
我发现了这个问题:Can I use Boost.Geometry.index.rtree with threads?,但它描述了更复杂的情况,当rtree被修改并从不同的线程查询时。这个答案含糊不清:“没有提升Rtree在任何方面都不是线程安全的”在答案中说明。但在评论中说:“查询是安全的,甚至可以为创建创建解决方法”。什么是正确答案?是否有任何资源,除了提出直接问题以提高作者,找出答案?
铊; DR:
如果我100%确定没有线程修改RTree,那么从不同的线程向boost::geometry::index::rtree
进行查询是否安全?
答案 0 :(得分:3)
回答链接问题:"没有提升Rtree在任何方面都不是线程安全的"。但是在评论中:"进行查询是安全的,甚至可以为创建创建解决方法"。谁是对的?
没有矛盾。亚当是作者。每个人都是对的。请注意,答案也说了
你/可以/并行运行多个只读操作。通常,库容器可以安全地从多个线程用于只读操作(尽管您可能希望快速扫描隐藏的任何可变成员(在实现中)。
通常,只要按位表示不变异,一切对于并发访问都是安全的。这与图书馆支持无关。
请注意,您不需要" 快速扫描"因为它发生了,因为Adam Wulkiewicz的权威评论。
脚注:仍然没有使库线程安全。这是正确的,因为C ++的内存模型没有按位常数数据的数据竞争。
答案 1 :(得分:0)
这似乎不是完整的问题。我正在阅读的内容分为两部分。第一部分应该是“我想优化我的程序。我应该怎么做呢?”
您应该使用分析器在优化之前进行测量!您可能会注意到在此过程中有更多重要的优化可用,并且可能会被推出可能的窗口。你过早地介绍了多线程。
您应该使用分析器在优化后进行测量!发现优化是微不足道的并不罕见。在多线程优化方面,根据您的测量结果,您应该看到处理一个任务需要稍长但是您可以同时处理四到八个在具有四核CPU的计算机上。如果稍长相当于4-8倍的因子,那么显然多线程是不必要的膨胀引入而不是优化。
第二部分,您已经以这两个陈述的形式提供了:
我100%肯定,虽然任何Module2工作的RTree都没有改变。
如果我100%确定没有线程修改RTree,那么从不同的线程向
boost::geometry::index::rtree
进行查询是否安全?
你应该使用锁。如果你不这样做,你将调用未定义的行为。我将解释为什么你应该在以后使用锁。
我建议对您描述的用例使用读/写锁(例如pthread_rwlock_t
)。这将允许您的线程同时访问资源,只要没有线程是尝试编写,并提供一个栅栏,以便将更新推送到线程。
为什么要使用锁?首先,它们保证您的代码能够正常运行;任何关于它是否安全的问题都会变得无效。其次,锁提供了一个围栏,在该围栏上可以将更新推送到线程;与您应该从中看到的收益金额相比,对性能影响的任何担忧都应该可以忽略不计。
您应该为每个帖子执行多个任务!这就是围栏很重要的原因。如果您的线程最终终止并且您最终在最后创建新线程,则会产生开销,这在执行优化时当然是不可取的。如果一个线程终止,尽管后面会有更多这些任务,那么该线程可能应该被暂停了。
预计您的优化可能会变成工作窃取线程池。当我们瞄准最重要的一个时,这就是优化的本质。毕竟,偶尔它是迄今为止最重要的,或者也许是唯一的瓶颈。优化此类瓶颈可能需要采取极端措施。
我之前强调“应该可以忽略不计”,因为你可能会在一定程度上看到性能的显着提升;尝试在具有4个核心(每个核心2500个线程)的处理器上尝试启动10000个线程(每个占用0.5到4.0MB堆栈空间,总共5-40GB)应该是不合理的。尽管如此,这是许多人出错的地方,如果他们有导演指导他们,他们将更有可能注意到......
如果您的任务涉及可以非阻塞的IO,您甚至可以在一个线程上运行多个任务。这通常是我在查看多线程之前会进行的优化,因为分析器会突出显示。