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