同時実行性は、アプリケーションのパフォーマンスを向上させるために複数のタスクを同時に実行できるようにする、現代のプログラミングにおける重要な概念です。
Python で同時実行性を実現するにはいくつかの方法がありますが、スレッド化とマルチプロセッシングが最もよく知られています。
この記事では、これら 2 つのメソッドを詳しく調査し、それらがどのように機能するかを理解し、実際のコード例とともに、それぞれをいつ使用するかについて説明します。
スレッド化とマルチプロセッシングについて話す前に、同時実行性の意味を理解することが重要です。
同時実行性とは、プログラムが複数のタスクまたはプロセスを同時に実行できることです。
これにより、特にファイルの読み取りや大量の計算などを行う必要がある場合に、プログラムのリソース使用率が向上し、実行速度が向上します。
同時実行性を実現するには、主に 2 つの方法があります:
Python では、同時実行性を実現する 2 つの主な方法が提供されています。
スレッド化を使用すると、スレッドと呼ばれる複数の小さなプロセス単位を同じプロセス内で実行し、同じメモリ空間を共有できます。
スレッドはプロセスよりも軽く、スレッド間の切り替えは高速です。
ただし、Python でのスレッド処理はグローバル インタープリター ロック (GIL) の対象となり、一度に 1 つのスレッドのみが Python コードを実行できるようになります。
Python のスレッド モジュールは、スレッドを作成および管理するためのシンプルかつ柔軟な方法を提供します。
基本的な例から始めましょう:
import threading import time def print_numbers(): for i in range(5): print(f"Number: {i}") time.sleep(1) # Creating a thread thread = threading.Thread(target=print_numbers) # Starting the thread thread.start() # Wait for the thread to complete thread.join() print("Thread has finished executing") # Output: # Number: 0 # Number: 1 # Number: 2 # Number: 3 # Number: 4 # Thread has finished executing
この例では:
スレッド処理は、ファイル操作、ネットワーク リクエスト、データベース クエリなど、プログラムが外部リソースの待機にほとんどの時間を費やす I/O バウンドのタスクに特に役立ちます。
スレッドを使用してファイルのダウンロードをシミュレートする例を次に示します:
import threading import time def download_file(file_name): print(f"Starting download of {file_name}...") time.sleep(2) # Simulate download time print(f"Finished downloading {file_name}") files = ["file1.zip", "file2.zip", "file3.zip"] threads = [] # Create and start threads for file in files: thread = threading.Thread(target=download_file, args=(file,)) thread.start() threads.append(thread) # Ensure all threads have finished for thread in threads: thread.join() print("All files have been downloaded.") # Output: # Starting download of file1.zip... # Starting download of file2.zip... # Starting download of file3.zip... # Finished downloading file1.zip # Finished downloading file2.zip # Finished downloading file3.zip # All files have been downloaded.
ファイルのダウンロードごとに個別のスレッドを作成して管理することにより、プログラムは複数のタスクを同時に処理でき、全体的な効率が向上します。
コード内の主要な手順は次のとおりです:
スレッド化により I/O バウンドのタスクのパフォーマンスが向上しますが、次のような制限があります。
マルチプロセッシングは、スレッドの代わりに別のプロセスを使用することで、スレッドの制限に対処します。
各プロセスには独自のメモリ空間と Python インタープリターがあり、マルチコア システムでの真の並列処理が可能になります。
これにより、マルチプロセッシングは大量の計算を必要とするタスクに最適になります。
Python のマルチプロセッシング モジュールを使用すると、プロセスを簡単に作成および管理できます。
Let’s start with a basic example:
import multiprocessing import time def print_numbers(): for i in range(5): print(f"Number: {i}") time.sleep(1) if __name__ == "__main__": # Creating a process process = multiprocessing.Process(target=print_numbers) # Starting the process process.start() # Wait for the process to complete process.join() print("Process has finished executing") # Output: # Number: 0 # Number: 1 # Number: 2 # Number: 3 # Number: 4 # Process has finished executing
This example is similar to the threading example, but with processes.
Notice that the process creation and management are similar to threading, but because processes run in separate memory spaces, they are truly concurrent and can run on different CPU cores.
Multiprocessing is particularly beneficial for tasks that are CPU-bound, such as numerical computations or data processing.
Here’s an example that calculates the square of numbers using multiple processes:
import multiprocessing def compute_square(number): return number * number if __name__ == "__main__": numbers = [1, 2, 3, 4, 5] # Create a pool of processes with multiprocessing.Pool() as pool: # Map function to numbers using multiple processes results = pool.map(compute_square, numbers) print("Squares:", results) # Output: # Squares: [1, 4, 9, 16, 25]
Here are the key steps in the code:
Since each process has its own memory space, sharing data between processes requires inter-process communication (IPC) mechanisms.
The multiprocessing module provides several tools for IPC, such as Queue, Pipe, and Value.
Here’s an example using Queue to share data between processes:
import multiprocessing def worker(queue): # Retrieve and process data from the queue while not queue.empty(): item = queue.get() print(f"Processing {item}") if __name__ == "__main__": queue = multiprocessing.Queue() # Add items to the queue for i in range(10): queue.put(i) # Create a pool of processes to process the queue processes = [] for _ in range(4): process = multiprocessing.Process(target=worker, args=(queue,)) processes.append(process) process.start() # Wait for all processes to complete for process in processes: process.join() print("All processes have finished.") # Output: # Processing 0 # Processing 1 # Processing 2 # Processing 3 # Processing 4 # Processing 5 # Processing 6 # Processing 7 # Processing 8 # Processing 9 # All processes have finished.
In this example:
While multiprocessing provides true parallelism, it comes with its own set of challenges:
Choosing between threading and multiprocessing depends on the type of task you're dealing with:
Use Threading:
Use Multiprocessing:
Concurrency in Python is a powerful way to make your applications run faster.
Threading is great for tasks that involve a lot of waiting, like network operations or reading/writing files, but it's not as effective for tasks that require heavy computations because of something called the Global Interpreter Lock (GIL).
On the other hand, multiprocessing allows for true parallelism, making it perfect for CPU-intensive tasks, although it comes with higher overhead and complexity.
データの処理、複数のネットワーク リクエストの処理、複雑な計算のいずれの場合でも、Python のスレッドおよびマルチプロセッシング ツールは、プログラムを可能な限り効率的かつ高速にするために必要なものを提供します。
以上がPython でのスレッド化とマルチプロセッシングによる同時実行性の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。