threadとprocess

マルチスレッド/プロセスまとめ(Ruby編)から

process(プロセス)

  • プログラムの実行単位
  • 固有のメモリ空間を持つ(リソースを共有しない)
  • マルチプロセスの場合、物理/仮想メモリ領域間のアドレス解決のオーバーヘッドが高い。

スレッド

  • プロセスの実行単位
  • 共通のメモリ空間を持つ(リソースを共有する)
  • マルチスレッドの場合、物理/仮想メモリ領域間のアドレス解決は発生しない。

Rubyにおけるマルチスレッド

  • GILが導入されたネイティブスレッド(バージョン1.9以降)
  • 1つのプロセスに複数のスレッドを生成できるが、GILにより実行できるスレッドは常に1つ。
  • マルチプロセッサの場合、時間単位に複数のプロセッサのスレッド間で処理が切り替わるため、あたかも並列処理しているように見える。
  • そのため全体の処理速度はシングルプロセッサの場合とほとんど変わらない。
  • ただし、IO待ちの際GILが解放 されるため、一時的な並列処理が可能になる。

multi thread

require "parallel"
require 'benchmark'
require "secure random"

id = 0
count = 0

exec_time = Benchmark.realtime do

  Parallel.each([*1..10], in_threads: 4) {|i|
    id = i

    100000.times do |ii|
      if id != i
        count += 1
      end
      id = i
      Digest::MD5.digest(SecureRandom.uuid)
    end
  }
end
puts exec_time
puts count

multi process

  • topで確認したらin_processes:で指定した数分PIDが増える
  • serverのcpu数を確認し合わせて使うのがいい
require "parallel"
require 'benchmark'
require "secure random"

id = 0
count = 0

exec_time = Benchmark.realtime do

  Parallel.each([*1..10], in_processes: 4) {|i|
    id = i

    100000.times do |ii|
      if id != i
        count += 1
      end
      id = i
      Digest::MD5.digest(SecureRandom.uuid)
    end
  }
end
puts exec_time
puts count

FiberとProcの違い

  • 「ブロックのコードを任意の場所で呼び出せる」だけではProcと変わりません
  • Fiber.yieldFiber.resumeを組み合わせて使うことによってProcと差別化できる。
  • generatorを作るときに有効
    • 「計算を途中までで止めて部分的な結果を返し、また続きから計算を再開する」ようなモノを ジェネレータ と呼ぶ
  • Fiberは親子関係を持ち、親からはresume、子からはFiber.yieldという非対称な呼び出し関係にあるため、コルーチンではなくセミコルーチンと呼んだほうが正確

resumeとyieldの例

f = Fiber.new do
  Fiber.yield 'return by yield' # 処理を親に戻す
  Fiber.yield 'return by yield again'
  'end of block'
end

puts '--- 1 ---'
f.resume #=> 'return by yield'
puts '--- 2 ---'
f.resume #=> 'return by yield again'
puts '--- 3 ---'
f.resume #=> 'end of block'
puts '--- 4 ---'
f.resume #=> FiberError: dead fiber called

ruby generatorで fibonacci数を順々に返す

fibonacci = Fiber.new do
  x, y = 0, 1
  loop do
    Fiber.yield y # yieldに渡した値がresumeの返り値となる
    x, y = y, x + y
  end
end

puts fibonacci.resume #=> 1
puts fibonacci.resume #=> 1
puts fibonacci.resume #=> 2
puts fibonacci.resume #=> 3
puts fibonacci.resume #=> 5
puts fibonacci.resume #=> 8
puts fibonacci.resume #=> 13

References

results matching ""

    No results matching ""