# Python Multiprocessing Module

The `multiprocessing` module allows you to create processes that run independently. Each process has its own Python interpreter and memory space, bypassing the Global Interpreter Lock (GIL). This makes it ideal for CPU-bound tasks.

## Importing the Module

```python
import multiprocessing
```

## The `Process` Class

To create a process, you create an instance of the `Process` class and pass it the function you want to run.

```python
import multiprocessing
import time

def worker(num):
    print(f'Worker: {num}')
    time.sleep(1)

if __name__ == '__main__':
    jobs = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,))
        jobs.append(p)
        p.start()
    
    for p in jobs:
        p.join()
```

## The `Pool` Class

The `Pool` class offers a convenient means of parallelizing the execution of a function across multiple input values, distributing the input data across processes (data parallelism).

```python
import multiprocessing

def square(x):
    return x * x

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(square, [1, 2, 3, 4, 5])
        print(results)
```

## Inter-Process Communication

### Queue

The `Queue` class is a thread and process safe queue.

```python
import multiprocessing

def producer(q):
    q.put('hello')

def consumer(q):
    print(q.get())

if __name__ == '__main__':
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target=producer, args=(q,))
    p2 = multiprocessing.Process(target=consumer, args=(q,))
    
    p1.start()
    p2.start()
    
    p1.join()
    p2.join()
```

## Sharing State

### Shared Memory

Data can be stored in a shared memory map using `Value` or `Array`.

```python
import multiprocessing

def f(n, a):
    n.value = 3.14159
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ == '__main__':
    num = multiprocessing.Value('d', 0.0)
    arr = multiprocessing.Array('i', range(10))

    p = multiprocessing.Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print(num.value)
    print(arr[:])
```

[[programming/python/python]]