5

我正在编写一个程序,将数据从四个 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 分钟。

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

4

2 回答 2

3

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

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

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

于 2013-07-14T00:11:28.070 回答
0

It's impossible to give a conclusive answer to why your parallel problem is slower than the sequential one without a lot more information, but one possibility is:

With the sequential program, your disk seeks to the first file, reads it all out, seeks to the 2nd file, reads it all out, and so on.

With the parallel program, the disk head keeps moving back and forth trying to service I/O requests from all 4 threads.

I don't know if there's any way to measure disk seek time on your system: if so, you could confirm whether this hypothesis is true.

于 2013-07-09T14:25:41.347 回答