Python > Advanced Python Concepts > Concurrency and Parallelism > Processes and the `multiprocessing` Module
Parallel Computation of Square Roots using `multiprocessing`
This code demonstrates how to leverage the `multiprocessing` module in Python to perform computationally intensive tasks in parallel. Specifically, it calculates the square roots of a list of numbers using multiple processes, significantly reducing the overall execution time compared to a sequential approach. This example showcases process creation, task distribution, and result aggregation.
Code Snippet
This code defines a function `calculate_square_root` that computes the square root of a given number. The main part of the script initializes a list of numbers and creates a `multiprocessing.Pool` with a number of processes equal to the CPU core count. The `pool.map` function applies the `calculate_square_root` function to each number in the list, distributing the work across the available processes. The results are then collected and printed. The process id is printed for clarity.
import multiprocessing
import math
import time
def calculate_square_root(number):
"""Calculates the square root of a number."""
start_time = time.time()
result = math.sqrt(number)
end_time = time.time()
print(f"Process ID: {multiprocessing.current_process().pid}, Number: {number}, Square Root: {result:.4f}, Time: {end_time - start_time:.4f} seconds")
return result
if __name__ == '__main__':
numbers = list(range(1, 11)) # List of numbers to process
num_processes = multiprocessing.cpu_count() # Determine the number of CPU cores
print(f"Running with {num_processes} processes.")
start_time = time.time()
with multiprocessing.Pool(processes=num_processes) as pool:
results = pool.map(calculate_square_root, numbers)
end_time = time.time()
print(f"Total execution time: {end_time - start_time:.4f} seconds")
print(f"Results: {results}")
Concepts Behind the Snippet
This snippet utilizes the following key concepts:
Real-Life Use Case
This pattern is ideal for computationally intensive tasks that can be easily divided into independent subtasks. Examples include:
Best Practices
Interview Tip
When discussing multiprocessing in interviews, be prepared to explain:
When to Use Them
Use the `multiprocessing` module when:
Memory Footprint
Each process created by `multiprocessing` has its own memory space. This means that each process will have its own copy of the data. For large datasets, this can lead to significant memory consumption. Consider using shared memory or memory-mapped files to reduce memory usage if appropriate. The main process also holds a copy of the returned values. The cost can be high.
Alternatives
Alternatives to `multiprocessing` for concurrency include:
Pros
Cons
FAQ
-
Why use `multiprocessing` instead of threading?
multiprocessing
allows for true parallelism by utilizing multiple CPU cores, bypassing the limitations of the Global Interpreter Lock (GIL) in Python. Threads, on the other hand, are typically more suitable for I/O-bound tasks where the GIL is not a significant bottleneck. -
How do I handle exceptions in worker processes?
Implement exception handling within the worker function using a try-except block. Consider using a queue or pipe to communicate exceptions back to the main process. -
How can I share data between processes?
You can use various mechanisms for inter-process communication (IPC), such as queues, pipes, shared memory, or memory-mapped files. Choose the appropriate method based on the amount of data being shared and the performance requirements.