CodeNebula
Python⚡Concurrencyintermediate

`multiprocessing` — True Parallelism

Python · Concurrency · Run with python3

Explanation

`multiprocessing.Process` launches a separate Python interpreter process — no GIL, true CPU parallelism. `Pool.map()` distributes work across N worker processes. `multiprocessing.Queue` and `Pipe` enable inter-process communication (IPC). `Value` and `Array` provide shared memory. The `spawn` start method (default on Windows/macOS) re-imports the module in each worker — guard the entry point with `if __name__ == "__main__":`. `ProcessPoolExecutor` (from `concurrent.futures`) is the higher-level API.

Real-World Scenario

Compressing 1,000 images: `Pool(os.cpu_count()).map(compress_image, image_paths)` distributes the CPU-bound work across all cores — linear speedup with core count (no GIL interference). ```python import multiprocessing import os import time def is_prime(n: int) -> bool: if n < 2: return False for i in range(2, int(n**0.5) + 1): if n % i == 0: return False return True def count_primes_in_range(args: tuple[int, int]) -> int: lo, hi = args return sum(1 for n in range(lo, hi) if is_prime(n)) if __name__ == "__main__": N = 200_000 num_workers = os.cpu_count() or 4 chunk_size = N // num_workers ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(num_workers)] start = time.perf_counter() with multiprocessing.Pool(num_workers) as pool: counts = pool.map(count_primes_in_range, ranges) elapsed = time.perf_counter() - start print(f"Primes below {N}: {sum(counts)}") print(f"Time ({num_workers} workers): {elapsed:.2f}s") ```

Quick Snippet

snippet.py
import multiprocessing
import os
import time

def is_prime(n: int) -> bool:
    if n < 2: return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0: return False
    return True

def count_primes_in_range(args: tuple[int, int]) -> int:
    lo, hi = args
    return sum(1 for n in range(lo, hi) if is_prime(n))

if __name__ == "__main__":
    N = 200_000
    num_workers = os.cpu_count() or 4
    chunk_size  = N // num_workers
    ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(num_workers)]

    start = time.perf_counter()
    with multiprocessing.Pool(num_workers) as pool:
        counts = pool.map(count_primes_in_range, ranges)
    elapsed = time.perf_counter() - start

    print(f"Primes below {N}: {sum(counts)}")
    print(f"Time ({num_workers} workers): {elapsed:.2f}s")

Full Example

multiprocessing_basics.py
# Compile: python3 multiprocessing_basics.py
# Output:
# Primes below 50000 and time printed

import multiprocessing
import os
import time

def is_prime(n: int) -> bool:
    if n < 2: return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0: return False
    return True

def count_primes_in_range(args: tuple) -> int:
    lo, hi = args
    return sum(1 for n in range(lo, hi) if is_prime(n))

if __name__ == "__main__":
    N = 50_000
    num_workers = min(os.cpu_count() or 2, 4)
    chunk_size  = N // num_workers
    ranges = [(i * chunk_size, (i + 1) * chunk_size) for i in range(num_workers)]

    start = time.perf_counter()
    with multiprocessing.Pool(num_workers) as pool:
        counts = pool.map(count_primes_in_range, ranges)
    elapsed = time.perf_counter() - start

    print(f"Primes below {N}: {sum(counts)}")
    print(f"Time ({num_workers} workers): {elapsed:.3f}s")
Run command
python3 multiprocessing_basics.py