raku perl6对哈希和数组的推和弹出操作是原子和线程安全的吗?

问题描述 投票:2回答:1

我有一个庞大的数据文件(接近4T),需要处理。我在4核CPU上使用4个线程。第一个线程分析文件的第一季度,依此类推。在分析了自己数据文件的四分之一部分之后,所有线程都需要将其结果添加到相同的单个哈希和单个数组中。那么,散列和数组原子和线程安全的“ push”,“ pop”,“ shift”和“ unshift”操作是否安全,还是我不得不求助于信号灯之类的更复杂的机制?

multithreading hash push semaphore raku
1个回答
2
投票

不,它们既不是原子级的也不是线程安全的,并且在多个线程中使用会导致崩溃或数据不一致。

也就是说,即使是这样,涉及相同数据结构的大量争用的设计在添加更多线程时伸缩性也会很差。这是因为硬件在面对并行性时的工作方式。简要地:

  • 内存性能在很大程度上取决于缓存
  • 某些缓存级别是每个CPU内核
  • 写入内存意味着将其专门放入当前内核的缓存中
  • [从一个内核的高速缓存中移出以进行写入的过程非常昂贵(耗时60-100个周期)

您可以使用锁定来获得正确性。为此,我不建议直接使用锁,而要查看OO::Monitors之类的模块,您可以在其中将哈希封装在对象中,并在边界处进行锁定。

如果您在共享数据结构上进行的推送次数少于产生要推送项目的工作量,那么您可能不会在数据结构周围的锁定和争用方面遇到瓶颈。但是,如果您每秒要执行数千次push或类似的操作,则建议您寻找替代设计。例如:

  1. 将工作分解成每个工人的一部分
  2. 使用start引发每个工作人员,这将返回Promise。将Promise s放入数组。
  3. 让每个Promise返回其产生的项目的数组或哈希。
  4. 合并每个结果。例如,如果每个都返回一个数组,则my @all-results = flat await @promises;或类似内容足以将所有结果收集在一起。

您可能会发现自己的问题很适合parallel iterator paradigm, using hyper or race,在这种情况下,您甚至不需要中断工作或自己设置工人;相反,您可以选择度数和批次大小。

© www.soinside.com 2019 - 2024. All rights reserved.