xref: /aosp_15_r20/external/grpc-grpc/examples/python/multiprocessing/README.md (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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