实现在红宝石同步障碍(Implementing a synchronization barrier

2019-08-03 16:51发布

我试图“复制” CUDA的行为__synchtreads()在Ruby中的功能。 具体来说,我有一组N需要执行一些代码,那么所有与业务的其余部分,然后再继续在执行中等待对方在中点线。 例如:

x = 0

a = Thread.new do
  x = 1
  syncthreads()  
end

b = Thread.new do 
  syncthreads()
  # x should have been changed
  raise if x == 0
end

[a,b].each { |t| t.join }

什么工具,我需要用它来做到这一点? 我试图用一个全球性的哈希值,然后睡觉,直到所有的线程都设置一个标志,指示他们与代码的第一部分完成。 我不能让它正常工作; 它导致挂起和死锁。 我我需要使用的组合MutexConditionVariable ,但我不能确定,为什么/如何。

编辑:50组的意见和没有回答! 看起来像一个赏金的候选人...

Answer 1:

让我们来实现同步障碍。 它必须知道它的线程将处理的数量,N,在前面。 在第N - 1调用sync障碍将导致调用线程等待。 呼叫数n将唤醒所有线程起来。

class Barrier
  def initialize(count)
    @mutex = Mutex.new
    @cond = ConditionVariable.new
    @count = count
  end

  def sync
    @mutex.synchronize do
      @count -= 1
      if @count > 0
        @cond.wait @mutex
      else
        @cond.broadcast
      end
    end
  end
end

的整个身体sync是一个关键的部分,即,它不能由两个线程同时执行。 因此,呼叫Mutex#synchronize

当降低值@count为正的线程被冻结。 路过互斥体作为参数调用ConditionVariable#wait关键是要防止死锁。 它使互斥冻结线程之前解锁。

一个简单的实验开始1K线程并使得它们添加元素添加到数组。 首先,他们加个零,那么它们同步,并添加的。 预期的结果是一个排序后的数组具有2k个元素,其中每千是零和1K的。

mtx = Mutex.new
arr = []
num = 1000
barrier = Barrier.new num
num.times.map do
  Thread.start do
    mtx.synchronize { arr << 0 }
    barrier.sync
    mtx.synchronize { arr << 1 }
  end
end .map &:join;
# Prints true. See it break by deleting `barrier.sync`.
puts [
  arr.sort == arr,
  arr.count == 2 * num,
  arr.count(&:zero?) == num,
  arr.uniq == [0, 1],
].all?

作为事实上,有一个名为屏障宝石这不正是上述我。

最后要注意,不要使用睡在这样的情况下等待。 这就是所谓的忙等待和被认为是不好的做法 。



Answer 2:

有可能是具有线程等待对方的优点。 但我认为,它是清洁有螺纹实际上是在“中点”完成的,因为你的问题很明显impliest该线程需要彼此的结果的‘中点’。 简洁的设计解决方案是让他们完成,提供他们工作的结果,并开始一组全新的基于这些线程。



文章来源: Implementing a synchronization barrier in Ruby