【问题标题】:Ruby performance with multiple threads vs one thread多线程与单线程的 Ruby 性能
【发布时间】:2013-07-09 13:28:04
【问题描述】:

我正在编写一个程序,将数据从四个 XML 文件加载到四个不同的数据结构中。它有这样的方法:

def loadFirst(year)
  File.open("games_#{year}.xml",'r') do |f|
    doc = REXML::Document.new f
    ...
  end
end
def loadSecond(year)
  File.open("teams_#{year}.xml",'r') do |f|
    doc = REXML::Document.new f
    ...
  end
end

etc...

我原本只是用一个线程,一个接一个地加载文件:

def loadData(year)
  time = Time.now
  loadFirst(year)
  loadSecond(year)
  loadThird(year)
  loadFourth(year)
  puts Time.now - time
end

然后我意识到我应该使用多个线程。我的期望是,在单独的线程上从每个文件加载的速度几乎是顺序加载的四倍(我有一台配备 i7 处理器的 MacBook Pro):

def loadData(year)
  time = Time.now
  t1 = Thread.start{loadFirst(year)}
  t2 = Thread.start{loadSecond(year)}
  t3 = Thread.start{loadThird(year)}
  loadFourth(year)
  t1.join
  t2.join
  t3.join
  puts Time.now - time
end

我发现使用多线程的版本实际上比另一个慢。这怎么可能?差别在 20 秒左右,每次大约需要 2 到 3 分钟。

线程之间没有共享资源。每个都打开不同的数据文件并将数据加载到与其他数据不同的数据结构中。

【问题讨论】:

  • 您使用的是哪个版本的语言和哪个虚拟机?我相信大多数 ruby​​ 运行时仍在使用“绿色”线程(阅读:实际上不是多线程,而是在单个线程中模拟)
  • 经典 ruby​​ 有一个 GIL - 你不会得到计算并行性,因为通常一次只运行一个线程(IO 和其他一些情况除外)。用 jruby 试试你的代码
  • 也许您可以编写程序打印出每个线程开始和结束时的当前时间(必要时最多使用 sec)。然后你会更好地了解正在发生的事情。特别是,你应该能够看到第n+1个线程是否在第n个线程结束之前开始。
  • 请参阅this link 了解有关各种 ruby​​ 运行时中线程实现的详细信息。您实际上并没有使用 Ruby 1.9.3 获得并发执行。这是一门很棒的语言,但在某些方面实现还有些年轻。
  • 我的猜测是有多个线程会导致某种交换争用被添加。我想你可以分析它......

标签: ruby multithreading performance concurrency


【解决方案1】:

我认为(但我不确定)问题在于您正在读取(使用多个线程)放置在同一个磁盘上的内容,因此您的所有线程无法同时运行,因为它们等待 IO(磁盘)。

几天前我不得不做类似的事情(但从网络获取数据),顺序与线程之间的差异很大。

一种可能的解决方案是加载所有文件内容,而不是像在代码中那样加载它。在您的代码中,您逐行阅读内容。如果您加载所有内容然后对其进行处理,您应该能够执行得更好(因为线程不应该等待 IO)

【讨论】:

  • 谢谢,这是个好主意。
【解决方案2】:

在没有更多信息的情况下,不可能给出关于为什么您的并行问题比顺序问题慢的结论性答案,但一种可能性是:

使用顺序程序,您的磁盘会查找第一个文件,将其全部读取,然后查找到第二个文件,然后将其全部读取,依此类推。

在并行程序中,磁头不断来回移动,试图为所有 4 个线程的 I/O 请求提供服务。

我不知道是否有任何方法可以测量您系统上的磁盘寻道时间:如果有,您可以确认这个假设是否正确。

【讨论】:

  • 有点题外话:我在 Ruby 上使用线程并行来同时处理多个网络请求,它对我的​​程序效率产生了奇迹。那是在 MRI (CRuby) 上。因此,并不是说您必须迁移到 JRuby 才能从使用线程进行并行 I/O 中获得任何好处。
猜你喜欢
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-01
  • 2021-09-08
相关资源
最近更新 更多