|  | @@ -1,16 +1,19 @@
 | 
	
		
			
				|  |  |  ## Multiprocessing with gRPC Python
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  Multiprocessing allows application developers to sidestep the Python global
 | 
	
		
			
				|  |  | -interpreter lock and achieve true concurrency on multicore systems.
 | 
	
		
			
				|  |  | +interpreter lock and achieve true parallelism on multicore systems.
 | 
	
		
			
				|  |  |  Unfortunately, using multiprocessing and gRPC Python is not yet as simple as
 | 
	
		
			
				|  |  |  instantiating your server with a `futures.ProcessPoolExecutor`.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  The library is implemented as a C extension, maintaining much of the state that
 | 
	
		
			
				|  |  |  drives the system in native code. As such, upon calling
 | 
	
		
			
				|  |  | -[`fork`](http://man7.org/linux/man-pages/man2/fork.2.html), much of the
 | 
	
		
			
				|  |  | -state copied into the child process is invalid, leading to hangs and crashes.
 | 
	
		
			
				|  |  | +[`fork`](http://man7.org/linux/man-pages/man2/fork.2.html), any threads in a
 | 
	
		
			
				|  |  | +critical section may leave the state of the gRPC library invalid in the child
 | 
	
		
			
				|  |  | +process. See this [excellent research
 | 
	
		
			
				|  |  | +paper](https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf)
 | 
	
		
			
				|  |  | +for a thorough discussion of the topic.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -However, calling `fork` without `exec` in your python process is supported
 | 
	
		
			
				|  |  | +Ccalling `fork` without `exec` in your process *is* supported
 | 
	
		
			
				|  |  |  *before* any gRPC servers have been instantiated. Application developers can
 | 
	
		
			
				|  |  |  take advantage of this to parallelize their CPU-intensive operations.
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -18,11 +21,7 @@ take advantage of this to parallelize their CPU-intensive operations.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  This example calculates the first 10,000 prime numbers as an RPC. We instantiate
 | 
	
		
			
				|  |  |  one server per subprocess, balancing requests between the servers using the
 | 
	
		
			
				|  |  | -[`SO_REUSEPORT`](https://lwn.net/Articles/542629/) socket option. Note that this
 | 
	
		
			
				|  |  | -option is not available in `manylinux1` distributions, which are, as of the time
 | 
	
		
			
				|  |  | -of writing, the only gRPC Python wheels available on PyPI. To take advantage of this
 | 
	
		
			
				|  |  | -feature, you'll need to build from source, either using bazel (as we do for
 | 
	
		
			
				|  |  | -these examples) or via pip, using `pip install grpcio --no-binary grpcio`.
 | 
	
		
			
				|  |  | +[`SO_REUSEPORT`](https://lwn.net/Articles/542629/) socket option.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  ```python
 | 
	
		
			
				|  |  |  _PROCESS_COUNT = multiprocessing.cpu_count()
 |