Pythonの並行処理(Concurrency)と並列処理(Parallelist)
並行処理(Concurrency)
並行処理は、複数のタスクを同時に実行するように見せかける技術です。シングルスレッドでも、タスクを切り替えて実行することで、あたかも複数のタスクが同時に進行しているように見えます。各タスクは、他のタスクの完了を待たずに進行できるため、CPUのリソースを効率よく使うことができます。
Pythonでの並行処理は主にasyncioやthreadingによって実現されますが、asyncioはシングルスレッドで動作し、タスクの切り替えを効率的に行う仕組みです。これにより、I/Oバウンドな操作(例えば、ネットワーク通信やファイルの読み書き)が他の処理をブロックせずに進行します。
並列処理(Parallelist)
並列処理は、複数のタスクを物理的に同時に実行することです。これは通常、複数のCPUコアやスレッドを使って実現します。並列処理では、複数のタスクが実際に同時に動いているため、CPUバウンドな処理(大量の計算を必要とするタスクなど)を高速に処理することが可能です。
Pythonでは、threadingを使うことでマルチスレッドを利用して並列処理が可能です。ただし、PythonのGIL(Global Interpreter Lock)の影響により、完全な並列処理を実現することが難しい場合があります。threadingは同時に動作しているように見えますが、GILによって1つのスレッドしか実際には動作していないことが多いため、特にCPUバウンドなタスクでは効果が限定的です。
並行処理と並列処理の違い
並行処理 (Concurrency):
- 複数のタスクが同時に「進行している」ように見えるが、実際にはタスクの切り替えを行っているだけ
- Pythonのasyncioはこの仕組みを使って、シングルスレッドで効率的に処理を進める
- 主にI/Oバウンドなタスクに向いている(例:ネットワーク通信、ファイル操作)
並列処理 (Parallelism):
- 複数のタスクが物理的に同時に実行される
- Pythonのthreadingやmultiprocessingを使って、複数のスレッドやプロセスで処理を並列化できる
- GILの影響でthreadingによるパフォーマンス改善は見込めない
- pythonで並列処理をしたい場合はmultiprocessingが有効
- CPUバウンドなタスクに向いている(例:大量の計算、データ処理)
コルーチン(Coroutine)とタスク(Task)の違い
コルーチン(Coroutine)
コルーチンとは:
コルーチンは、非同期関数の実行可能な単位です。async defで定義された関数を呼び出すと、コルーチンオブジェクトが返されます。コルーチン自体は単に「待機されるべき処理の定義」であり、実行されるためにはイベントループでスケジュールされる必要があります。
特徴:
コルーチンは、awaitキーワードを使って非同期的に処理を待つことができます。
コルーチンを直接実行しようとしても、すぐには動作しません。イベントループでawaitまたはasyncio.run()などを使って実行される必要があります。
import asyncio
async def my_coroutine():
print("Coroutine started")
await asyncio.sleep(1)
print("Coroutine ended")
# my_coroutine()はコルーチンオブジェクトを返すだけで、この時点では実行されない
coroutine = my_coroutine()
print(coroutine) # <coroutine object my_coroutine at 0x...>
# 実行するにはイベントループでawaitする必要がある
asyncio.run(coroutine)
タスク(Task)
タスクとは:
タスクは、コルーチンを実行するためのラッパーオブジェクトです。タスクはコルーチンをイベントループにスケジュールして実行させます。タスクを生成すると、コルーチンは自動的にスケジュールされ、バックグラウンドで並行して実行されます。
特徴:
asyncio.create_task()を使うことでコルーチンをタスクとしてスケジュールし、イベントループで実行できます。
タスクはイベントループが回っている間に他のタスクと並行して実行され、結果が返されるか、例外が発生すると完了します。
タスクは一度スケジュールされるとすぐに実行され始め、awaitでその結果を待つことができますが、待たずにタスクがバックグラウンドで実行され続けることも可能です。
コードをコピーする
import asyncio
async def my_coroutine():
print("Coroutine started")
await asyncio.sleep(1)
print("Coroutine ended")
async def main():
# コルーチンをタスクとしてスケジュール
task = asyncio.create_task(my_coroutine())
print("Task created, coroutine is now running in the background...")
# タスクの完了を待つ
await task
asyncio.run(main())