1## Multiprocessing with gRPC Python 2 3Multiprocessing allows application developers to sidestep the Python global 4interpreter lock and achieve true parallelism on multicore systems. 5Unfortunately, using multiprocessing and gRPC Python is not yet as simple as 6instantiating your server with a `futures.ProcessPoolExecutor`. 7 8The library is implemented as a C extension, maintaining much of the state that 9drives the system in native code. As such, upon calling 10[`fork`](http://man7.org/linux/man-pages/man2/fork.2.html), any threads in a 11critical section may leave the state of the gRPC library invalid in the child 12process. See this [excellent research 13paper](https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf) 14for a thorough discussion of the topic. 15 16Calling `fork` without `exec` in your process *is* supported 17before any gRPC servers have been instantiated. Application developers can 18take advantage of this to parallelize their CPU-intensive operations. 19 20## Calculating Prime Numbers with Multiple Processes 21 22This example calculates the first 10,000 prime numbers as an RPC. We instantiate 23one server per subprocess, balancing requests between the servers using the 24[`SO_REUSEPORT`](https://lwn.net/Articles/542629/) socket option. 25 26```python 27_PROCESS_COUNT = multiprocessing.cpu_count() 28``` 29 30On the server side, we detect the number of CPUs available on the system and 31spawn exactly that many child processes. If we spin up fewer, we won't be taking 32full advantage of the hardware resources available. 33 34## Running the Example 35 36To run the server, 37[ensure `bazel` is installed](https://docs.bazel.build/versions/master/install.html) 38and run: 39 40``` 41bazel run //examples/python/multiprocessing:server & 42``` 43 44Note the address at which the server is running. For example, 45 46``` 47... 48[PID 107153] Binding to '[::]:33915' 49[PID 107507] Starting new server. 50[PID 107508] Starting new server. 51... 52``` 53 54Note that several servers have been started, each with its own PID. 55 56Now, start the client by running 57 58``` 59bazel run //examples/python/multiprocessing:client -- [SERVER_ADDRESS] 60``` 61 62For example, 63 64``` 65bazel run //examples/python/multiprocessing:client -- [::]:33915 66``` 67 68Alternatively, generate code using the following and then run the client and server 69directly: 70 71```python 72cd examples/python/helloworld 73python -m grpc_tools.protoc -I . prime.proto --python_out=. --grpc_python_out=. 74``` 75