2013-07-09 14 views
5

4つのXMLファイルのデータを4つの異なるデータ構造にロードするプログラムを作成しています。これは、このようなメソッドがあります。複数のスレッドを持つRubyのパフォーマンスと1つのスレッド

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 

その後、私は、私は複数のスレッドを使用する必要があることに気づきました。私がいることがわかった何

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 

:私の期待は別のスレッド上の各ファイルからの読み込みが早くそれをすべて順番に(私はi7プロセッサー搭載するMacBook Proを持って)やって4倍に非常に近いだろうということでした実際には複数のスレッドを使用しているバージョンのほうが遅いです。これはどうやってできますか?違いは約20秒で、それぞれ約2〜3分かかります。

スレッド間に共有リソースはありません。それぞれ異なるデータファイルを開き、他のデータ構造とは異なるデータ構造にデータをロードします。

+2

使用している言語のバージョンと使用しているVMはどちらですか?私は、ほとんどのRubyランタイムはまだ "緑色"のスレッドを使用していると信じています(実際にはマルチスレッドではなく、1つのスレッドでエミュレートされます) –

+0

私は通常のRubyバージョン1.9.3を使用しています。私はちょっと調べて、ファイルの1つが他のものよりもはるかに多くのデータを持っていることを理解しました。そのため、パフォーマンスが4倍に変化しない理由を説明します。しかし、3つの他のものはまだ総体的に1分以上かかるので、私は複数のスレッドを使用して分の領域でパフォーマンスの向上を期待します... –

+2

古典的なルビーはGILを持っています - あなたは一般的な1つのスレッドが一度に1つずつ実行されます(IOやその他の場合の例外を除きます)。 jrubyでコードを試してください –

答えて

3

IO(ディスク)を待つため、すべてのスレッドが同時に実行できないように、同じディスクに複数のスレッドの内容を読み込んでいることが問題だと思います。 。

数日前、私は同じようなことをしましたが(ネットワークからデータを取得していました)、シーケンシャルとスレッドの違いは大きかったです。

可能な解決策は、コードで行ったのと同じように読み込むのではなく、すべてのファイルコンテンツを読み込むことです。あなたのコードでは、内容を1行ずつ読み込みます。すべてのコンテンツを読み込んで処理すると、スレッドがIOを待つべきではないので、はるかに優れたパフォーマンスが得られるはずです

+0

ありがとう、これは素晴らしい考えです。 –

0

それはあなたのパラレルの問題は、より多くの情報なしシーケンシャル1よりも遅い理由に決定的な答えを与えることは不可能だが、一つの可能​​性がある:逐次プログラムで

、あなたのディスクは最初のファイルにシークし、それをすべて読み込んだり、2番目のファイルを探したり、すべてを読み込んだりするなどです。

パラレルプログラムでは、ディスクヘッドが前後に移動して、4つのスレッドすべてからのI/O要求を処理しようとします。

システムでディスクのシーク時間を測定する方法があるかどうかわかりません。もしそうなら、この仮説が真であるかどうかを確認できます。

+2

少しオフトピック:私は、複数のネットワーク要求を同時に処理するためにRuby上でスレッドの並列処理を使用しており、私のプログラムの効率が不思議でした。それはMRI(CRuby)上にあった。したがって、並列I/Oにスレッドを使用する利点を得るためにJRubyに移動する必要があるかのようにはなりません。 –

関連する問題