/ / Rubyのスレッドは並行性を向上させますか? - ruby​​-on-rails、ruby、マルチスレッド

Rubyのスレッドは並行性を改善しますか? - ruby​​-on-rails、ruby、マルチスレッド

私の質問はMRIに固有です。 Ruby 1.9のすべてのスレッドはネイティブですが、MRIは一度に1つずつ実行し続けているようです。 MRIではスレッドの並列実行は不可能ですが、スレッドを使用するとプログラムの並行性が向上します。

言い換えれば、スレッドを使用してたくさんのファイルをS3にアップロードすることによるメリットはありますか?

# https://gist.github.com/milesmatthias/25c15fd8384d4a7e76f2

...

file_number = 0
mutex       = Mutex.new
threads     = []

thread_count.times do |i|
threads[i] = Thread.new {
until files.empty?
mutex.synchronize do
file_number += 1
Thread.current["file_number"] = file_number
end
file = files.pop rescue nil
next unless file

data = File.open(file)

if File.directory?(data)
data.close
next
else
obj = s3_bucket.objects[path]
obj.write(data, { acl: :public_read })
data.close
end

end
}
end
threads.each { |t| t.join }

...

回答:

回答№1は2

Ruby MRI(a.k.a.YARV)スレッドは、いくつかの種類の操作、特にI / Oを改善することができます。

VMは、グローバルロックのために、マルチコアプロセッサ上であっても、一度に1つのスレッドを実行します。

VMはいくつかのI / Oを含む操作。スレッドがI / O操作を待っているとき、Rubyは制御を次のスレッドに移します。また、ネイティブC拡張などのRuby以外のコードをスレッドが呼び出すことも可能で、これらは並列で実行することもできます。

AWSにI / Oアップローダーアプリを構築したとき、私たちはベンチマークでは、実際には最大約100スレッドのスループットを得ることができました。私たちは非常に高速なネットワーク接続を持っていました。新しい接続を開くために比較的長い時間がかかったため、スレッドの主な利点が得られました。

あなたの走行距離は変化するので、ベンチマーク。


回答№2の場合は3

Rubyのスレッドは並行性を向上させますが、並行性は向上させません並列性を高める。つまり、スレッドは複数のものを同時に処理(並行処理)することができるスレッドですが、同時に複数の処理を同時に行うことはできません(並列処理)。

なぜこの違いが重要ですか? コードに多くのCPU時間が必要な場合は、すべてのスレッドが同じCPUを使用する必要があるため、スレッドからは改善されません。しかし、あなたのコードが多くのIO(CPUが頻繁にアイドリングしていることを意味する)を行うと、全体のパフォーマンスが大幅に向上する可能性があります。

私の例では(S3へのファイルのアップロード)、ネットワーク帯域幅に応じてパフォーマンスが向上することが期待されます。


回答№3の場合は3

YARVには、同時に2つのスレッドがインタプリタループに入るのを防ぐGiant VM Lock(GVL)があります。それは本当です。

しかしこれは、Rubyコード(より正確にはYARVバイトコード)を同時に実行する2つの並列スレッドを持つことができないことを意味します。君は できる 同じコードを実行する並列スレッドを持つ(そして、コアライブラリ全体、標準ライブラリの大きな部分、そしていくつかのGemは実際RubyではなくC言語で書かれています)、並列スレッドがI / Oをやり遂げるのを待つことができます。並列スレッドで好きなもの(Rubyコードの実行を除く)

そう、はい、スレッド できる YARVでもパフォーマンスを改善します。