Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python multiprocess profiling

I'm struggling to figure out how to profile a simple multiprocess python script

import multiprocessing import cProfile import time def worker(num):     time.sleep(3)     print 'Worker:', num  if __name__ == '__main__':     for i in range(5):         p = multiprocessing.Process(target=worker, args=(i,))         cProfile.run('p.start()', 'prof%d.prof' %i) 

I'm starting 5 processes and therefore cProfile generates 5 different files. Inside of each I want to see that my method 'worker' takes approximately 3 seconds to run but instead I'm seeing only what's going on inside the 'start'method.

I would greatly appreciate if somebody could explain this to me.

Update: Working example based on accepted answer:

import multiprocessing import cProfile import time def test(num):     time.sleep(3)     print 'Worker:', num  def worker(num):     cProfile.runctx('test(num)', globals(), locals(), 'prof%d.prof' %num)   if __name__ == '__main__':     for i in range(5):         p = multiprocessing.Process(target=worker, args=(i,))         p.start() 
like image 371
barmaley Avatar asked Jun 14 '12 21:06

barmaley


People also ask

How does Python multiprocess work?

multiprocessing is a package that supports spawning processes using an API similar to the threading module. The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads.

How does Python handle multiprocessing?

While using multiprocessing in Python, Pipes acts as the communication channel. Pipes are helpful when you want to initiate communication between multiple processes. They return two connection objects, one for each end of the Pipe, and use the send() & recv() methods to communicate.

How do I stop a Python multiprocess?

A process can be killed by calling the Process. terminate() function. The call will only terminate the target process, not child processes. The method is called on the multiprocessing.

Does Python have multiprocessing?

Python multiprocessing Pool can be used for parallel execution of a function across multiple input values, distributing the input data across processes (data parallelism). Below is a simple Python multiprocessing Pool example.


2 Answers

You're profiling the process startup, which is why you're only seeing what happens in p.start() as you say—and p.start() returns once the subprocess is kicked off. You need to profile inside the worker method, which will get called in the subprocesses.

like image 160
zigg Avatar answered Sep 23 '22 10:09

zigg


It's not cool enough having to change your source code for profiling. Let's see what your code is supposed to be like:

import multiprocessing import time def worker(num):     time.sleep(3)     print('Worker:', num)  if __name__ == '__main__':     processes = []     for i in range(5):         p = multiprocessing.Process(target=worker, args=(i,))         p.start()         processes.append(p)     for p in processes:         p.join() 

I added join here so your main process will wait for your workers before quitting.

Instead of cProfile, try viztracer.

Install it by pip install viztracer. Then use the multiprocess feature

viztracer --log_multiprocess your_script.py

It will generate an html file showing every process on a timeline. (use AWSD to zoom/navigate)

result of script

Of course this includes some info that you are not interested in(like the structure of the actual multiprocessing library). If you are already satisfied with this, you are good to go. However, if you want a clearer graph for only your function worker(). Try log_sparse feature.

First, decorate the function you want to log with @log_sparse

from viztracer import log_sparse  @log_sparse def worker(num):     time.sleep(3)     print('Worker:', num) 

Then run viztracer --log_multiprocess --log_sparse your_script.py

sparse log

Only your worker function, taking 3s, will be displayed on the timeline.

like image 31
minker Avatar answered Sep 24 '22 10:09

minker