50644


以下のコードにおいて，`parallelFor`メソッドの出力を順番はバラバラでよいので`valueList`に全て格納したいです．  
どのようにコードを記述すればよいのでしょうか．  
ご教授お願い致します．

（現在の実行結果も質問下部に掲載します）

【追加の質問】  
１点目：上記のようなコードをマルチスレッドとマルチプロセスの両方で動かせた場合，処理速度はどのくらい変わりますのでしょうか．  
２点目：スパコン等でマルチプロセスで実行させたいと考えていまして，どうにかしてマルチプロセスで実行できる方法は無いのでしょうか．

[code]

    require 'test/unit'
    require 'parallel'
    
    def parallelFor(value, b = nil)
    
      p "value = #{value}"
      p "b = #{b}"
    
      return value
    end
    
    class UnitTest < Test::Unit::TestCase
    
      def test_parallelFor
    
        valueList = []
    
        vv = [10, 11, 12, 13, 14]
        Parallel.each_with_index(vv, :in_processes => 4){|v, i|
          valueTrial = parallelFor(v, i == 0 ? true : nil)
          p "valueTrial = #{valueTrial}"
          valueList << valueTrial
        }
        p "valueList = #{valueList}"
    
      end
    
    end
    
[/code]

「テストコード実行結果」

[code]

    Started
    "value = 10"
    "b = true"
    "valueTrial = 10"
    "value = 11"
    "b = "
    "valueTrial = 11"
    "value = 12"
    "value = 13"
    "b = "
    "valueTrial = 13"
    "b = "
    "valueTrial = 12"
    "value = 14"
    "b = "
    "valueTrial = 14"
    "valueList = []"
    .
    Finished in 0.022698 seconds.
    
[/code]


CC BY-SA 4.0
2018-11-26T02:53:01.957
50625
2018-11-26T12:50:35.350
2018-11-26T03:48:08.393
30173
30173
question
ruby-on-rails ruby
Rubyのマルチプロセス処理後の結果を配列にまとめたいけどできない


Parallelの各プロセスで実行した結果を親側で集めたい場合は`Parallel#map`または`Parallel#map_with_index`を使用してください。例えば、次のように修正します。

[code]

    valueList = Parallel.map_with_index(vv, :in_processes => 4){|v, i|
      valueTrial = parallelFor(v, i == 0 ? true : nil)
      p "valueTrial = #{valueTrial}"
      valueTrial
    }
    
[/code]

Parallelのマルチスレッドは内部で`fork`を使用しています。子プロセスには親プロセスのメモリ内容がそのままコピーされますが、フォークされた時点でそれぞれのメモリは独立しており、子プロセス上での変更は親プロセスには反映されません。そのため、子プロセス側で変数やオブジェクトを変更しても、親プロセスには一切影響がなくなります。本来、フォークされた子で計算されたデータを親に渡したい場合は、pipe等のプロセス間通信を行う必要があります。

ここまでは`each`でも`map`でも同じです。しかし、`map`はプロセス間通信のためのpipeを自動的に生成し、Marshalを使って親子間でオブジェクトの受け渡しを行います。子プロセスのブロックで最後に評価された式の結果であるオブジェクトをMarshalダンプして、pipeを通して親に渡し、親プロセスではMarshalでオブジェクトを復元します。親プロセスは通常の`map`のようにそれぞれの子プロセスから得たオブジェクトを一つの配列としてまとめることになります。こうして、あたかも通常の`map`のように動作しながら、マルチプロセスでの並列処理でも最終的に結果をまとめた配列としてデータを得ることができます。なお、マルチプロセスと併用しても結果は変わりません。

* * *

> １点目：上記のようなコードをマルチスレッドとマルチプロセスの両方で動かせた場合，処理速度はどのくらい変わりますのでしょうか．

処理速度は条件、コードの内容、環境の違い、ボトルネックの場所によって大きく変わってきますので、一概に言えることはありません。実測してくださいとしか言えません。

> ２点目：スパコン等でマルチプロセスで実行させたいと考えていまして，どうにかしてマルチプロセスで実行できる方法は無いのでしょうか．

スパコンが対応していれば、普通に`fork`を使って下さい。UNIX/Linuxの処理系であれば使用できるはずです。Parallelは`fork`を使った並列処理を簡単に書くようにするためのライブラリにしか過ぎません。


CC BY-SA 4.0
2018-11-26T12:50:35.350
50644
2018-11-26T12:50:35.350
7347
50625
answer