🍣
Python multithreading and multiprocessing
背景
- マルチスレッドで動作しているプロセスを並列処理できるようにしたい。
multithreading
pythonでマルチスレッドを実装する場合、asyncioを用いて以下のように実装できるだろう。
import asyncio
class AsyncTask:
async def run(self):
print("async task!")
await asyncio.sleep(0.1)
if __name__ == "__main__":
asyncio.run(AsyncTask().run())
multiprocessing
pythonでマルチプロセス(並列処理)を実装する場合、以下のように実装できる(いくつかパターンがある)
import os
import sys
from multiprocessing import Pool
from typing import List
class Task:
def run(self):
print(f"DummyAsyncTask: Hello from process(id={os.getpid()})")
class ParallelTaskExecuter:
def __init__(self, num_processes: int):
self.num_processes = num_processes
def execute_tasks(self, tasks: List[Task]):
with Pool(processes=self.num_processes) as process:
for task in tasks:
process.apply(task.run)
if __name__ == "__main__":
executor = ParallelTaskExecuter(2)
executor.execute_tasks([Task() for _ in range(2)])
multiprorocessing and multithreading
次に考えるのが、非同期処理を並列に処理することだ。非同期タスクを並列に処理する場合を考える。
import asyncio
import os
import sys
from multiprocessing import Pool
from typing import List
class AsyncTask:
def run(self):
asyncio.run(self.__run())
async def __run(self):
print(f"DummyAsyncTask: Hello from process(id={os.getpid()})")
await asyncio.sleep(0.1)
sys.stdout.flush()
class ParallelAsyncTaskExecutor:
def __init__(self, num_processes: int):
self.num_processes = num_processes
def execute_tasks(self, tasks: List[AsyncTask]):
with Pool(processes=self.num_processes) as process:
res = [
process.apply_async(
task.run,
)
for task in tasks
]
for r in res:
r.wait()
if __name__ == "__main__":
execturor = ParallelAsyncTaskExecutor(2)
execturor.execute_tasks([AsyncTask() for _ in range(2)])
各プロセス内で非同期処理を実行させるようにする必要がある。
これに気づくのにかなり時間を使ってしまった。
Discussion
通りすがりの指摘みたいで申し訳ないのですが、参考までに共有させていただきます。
コルーチンと
asyncio
による同時実行は、基本的にはマルチスレッドではありません。 シングルスレッドでの非同期処理です。 以前のドキュメントでは明記されていました。「asyncio シングルスレッド」などで検索するとご参考になるかもしれません。
またこちらはただの参考情報ですが、マルチプロセスの処理は標準ライブラリ
concurrent.futures.ProcessPoolExecutor
というのもあります。 これはmultiprocessing
を使いやすくラップしてくれてるクラスなので、要件によっては便利に使えるかもしれません。指摘ありがとうございます!
asyncioはシングルスレッドなんですね。そういえばイベントループが使われているのもシングルスレッドで非同期処理をやっているからなのか。