質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

並列処理

複数の計算が同時に実行される手法

Q&A

1回答

2759閲覧

RubyのParallelで、プロセス間で変数を共有したい

d04062

総合スコア111

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

並列処理

複数の計算が同時に実行される手法

0グッド

0クリップ

投稿2020/08/10 01:27

編集2020/08/10 01:29

RubyのParallelで、プロセス間で変数を共有したいと考えています。
(全体での試行回数をカウントしたい)

in_threadsの場合は変数を共有できるのですが、in_processesの場合はうまく共有できません。
(プロセスごとに独立してカウントされてしまいます)

◆コード

ruby

1require 'parallel' 2 3$i = 0 4result = Parallel.map([1,2,3,4,5,6,7,8,9,10], in_processes: 5) do |n| 5 p $i+=1 6end 7

出力結果

1 1 2 2 1 1 3 1 3 2

in_processesをin_threadsとすれば

1 2 3 6 8 10 7 5 9 4

プロセスとスレッドの違いが詳しく理解できていないのですが、おおまかに

「プロセスは、分離していて、変数共有が難しく、処理が速い」
「スレッドは、共有されていて、お互いに作用しないようにプログラムに工夫が必要であったり、処理が遅い」
ということが大まかに理解しています。

(重たい処理をさせるとやはり数倍の速度差が出てきました)

◆プロセスとスレッドについて
https://qiita.com/masashi127/items/b186bbf20b4c9632cc86

◆並列時には変数のロックが必要
また、スレッドの場合は、変数を同時に使用してしまうことを避けるためにロックが必要というようなことも読みました。
(今の所、私のやっている内容では、ロックがなくても平気?たまたま重複しなかっただけかもしれません)

https://shirusu-ni-tarazu.hatenablog.jp/entry/2013/07/02/042448

私の技術レベルでは、
・スレッドにする際の相互作用を考えたプログラムが書けそうにないかもしれない (エラー時に気付け無いなど)
・速さを重視したいので、プロセスの方を利用したい

のですが、共有したい変数はどのように扱えばよいでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

グローバル変数はプロセス単位のものですので、別プロセスを立てた場合には共有できません。

…というより、並列実行にあたって、途中経過を共有するという挙動そのものを、できるだけ避けるべきです。

(例が模式的すぎてわからないのですが、具体的にプロセス間でどのような連携をしたいのでしょうか?)

投稿2020/08/10 01:31

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

d04062

2020/08/10 01:40 編集

>グローバル変数はプロセス単位のものですので、別プロセスを立てた場合には共有できません。 なるほど、ありがとうございます。 >例が模式的すぎてわからないのですが、具体的にプロセス間でどのような連携をしたいのでしょうか? 全体でどれだけの回数が思考されたかをカウントしたいためです。 また、そのカウント数によって、処理を分けたりしたいと考えています。
maisumakun

2020/08/10 01:45

> 全体でどれだけの回数が思考されたかをカウントしたいためです。 プロセスごとの回数を終了時に集計する、というのが妥当です。 > また、そのカウント数によって、処理を分けたりしたいと考えています。 個数管理は親プロセスで行って、子プロセスの作成時に状況を反映する、という形が適切かと思います。
d04062

2020/08/10 02:05

もう少し具体的な説明が必要でした。 例えば、全体で、10の倍数の処理のときには、追加処理を行い、 その追加処理が行われている際は、 他のプロセスは途中で待機するような ことを行いたいと考えています。 (シングルの場合と同じような感覚で使いたいです) >プロセスごとの回数を終了時に集計する、というのが妥当です。 >個数管理は親プロセスで行って、子プロセスの作成時に状況を反映する、という形が適切かと思います。 具体的にはどのような記述をすれば良いでしょうか?
maisumakun

2020/08/10 02:07

> シングルの場合と同じような感覚で使いたいです すみません、これが前提だったのですね。でしたら、自分の回答は参考にならないです。
maisumakun

2020/08/10 02:09

「10の倍数の処理のとき」にすることが、以前の結果を使うようなものでないのであれば、それだけ専用のプロセスに切り出す、というような解決策も考えられます…が、おそらくそういうスタイルで動かせるものではなさそうですね。
d04062

2020/08/10 02:12

すごくシンプルにテキストファイルに書き出せば良いだけかとも考えているのですが、 「多少処理が遅くなったり、変数管理のためだけにわざわざ書き出す必要のあるものなのか?」 というような考えで質問してみました。
d04062

2020/08/10 02:18

>「10の倍数の処理のとき」にすることが、以前の結果を使うようなものでないのであれば (私の認識が間違っていなければなのですが) 以前の処理を使うことはなさそうです 1回目の処理も、2回目の処理も、処理自体は独立していて、 ただ全体の回数によって、 ・処理を分岐すること (追加処理など) ・追加処理中に他が待機すること なので、 すごく単純には、全体で共有できる変数が1つあれば良いかな?と考えているところです
maisumakun

2020/08/10 02:21 編集

なぜ「他が待機する」必要があるのかが気になります。並列処理の性能向上には、待機のようなボトルネックを作らないことが重要です。 (そのままやるとすれば、9個だけ分散で実行する→10個目はメインスレッドで演算、を繰り返す、というような解決法も考えられます)
d04062

2020/08/10 02:33

>なぜ「他が待機する」必要があるのかが気になります。並列処理の性能向上には、待機のようなボトルネックを作らないことが重要です。 なるほど、もう少し詳しい情報が必要なのですね。 (規定の回数で行う処理だけでなく) 何らかの要因で、タイムアウトが発生した際に、 例外処理(ルーターの再起動やPC共通のリフレシュ処理など)を行うため、その間に待機する必要があるためです
maisumakun

2020/08/10 02:36

> 何らかの要因で、タイムアウトが発生した際に、例外処理(ルーターの再起動やPC共通のリフレシュ処理など)を行うため Parallel::Breakを使えばいいような気もします。 https://github.com/grosser/parallel#break
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問