やりたいこと
Invoker
クラスが複数のCommand
インスタンスを持っており、すべてのインスタンスでCommand.execute()
を並列処理で実行したい。
Python3
1class Command: 2 def __init__(self) -> None: 3 self.done = False 4 5 def execute(self) -> None: 6 #何かしらの処理 7 self.done = True 8 9class Invoker: 10 def __init__(self, commands:list[Command]) -> None: 11 self.commands:list[Command] = commands 12 13 def execute_all(self) -> None: 14 #並列処理を用いてself.commandsのすべてのインスタンスでCommand.execute()を実行したい。 15 16if __name__ == "__main__": 17 command_list = [Command(), Command(), Command(), Command()] 18 i = Invoker(command_list) 19 i.execute_all() 20
実行後にi.commands
の各要素がdone = True
となっていてほしい。
やったこと
下記のコードを作成し実行しました。
Python3
1from multiprocessing import Pool 2 3class Command: 4 def __init__(self) -> None: 5 self.done = False 6 7 def execute(self) -> None: 8 #何かしらの処理 9 self.done = True 10 11class Invoker: 12 def __init__(self, commands:list[Command]) -> None: 13 self.commands:list[Command] = commands 14 15 def execute_all(self) -> None: 16 p = Pool(4) 17 cmds = p.map(execute_wrapper, self.commands) 18 p.close() 19 20def execute_wrapper(c:Command) -> Command: 21 c.execute() 22 return c 23 24if __name__ == "__main__": 25 command_list = [Command(), Command(), Command(), Command()] 26 i = Invoker(command_list) 27 i.execute_all()
しかし、i.commands
の各要素を覗いてみたところ、すべてのCommand
オブジェクトでdone = False
となっていました。一方、cmds
の各要素のCommand
オブジェクトではdone = True
となっていました。
ならばself.commands = cmds
とすればよいかとも考えましたが、元のself.commands
と順番が同じであることを保証したいのであまり良い案だとは思えませんでした。
デバッガーを使用しexecute_wrapper
に渡されるc
オブジェクトのidを調べてみたところ、それぞれi.commands
の各要素のidとは異なっていました。
execute_wrapper
に渡されるc
を値渡しではなく参照渡しできれば解決するのではないかと考えましたが、そもそもプロセスをforkするので参照渡しは不可能なのか?とも考えました(見当違いかもしれませんが、、、)。参照渡し等ではなく、もっと別のスマートな解決策があればそちらも教えていただきたいです。
並列処理についてはあまり良くわかっていないので、前提知識などが抜け落ちていた場合はご教示いただければと思います。よろしくお願いします。
環境
- Windows10
- Python 3.10.0
- VSCode 1.62.3
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/24 02:36
2021/11/24 11:48