2015-11-03 5 views
2

У меня есть сценарий python, который использует mpi4py, называемый main_parallel.py. Я могу измерить время, используя time форму cli, но как я могу составить профиль, похожий на cProfile? Мне нравится видеть номер вызова для каждой части кода. Я не могу использовать cProfile, потому что это только для серийного кода.Профилированный скрипт python с mpi4py

Спасибо!

ответ

3

Почему вы не можете использовать cprofile? Ты пробовал?

Для MPICH, я побежал, как это:

$ mpiexec -l -np 4 python -m cProfile ./simple-io.py doodad 

Это дает мне 4 набора выходных данных, но «-l» аргумент перечисляет ранг MPI перед каждым битом продукции. Обратите внимание: аргумент '-l' является специфичным для MPICH. OpenMPI использует --tag-output. Другие реализации могут использовать что-то еще.

Я вижу, что cprofile может принимать аргумент имени файла. сделать выходной файл для каждого-ранга, а затем обработать его с Показателями

% python 
Python 2.7.10 (default, Oct 14 2015, 16:09:02) 
[GCC 5.2.1 20151010] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import pstats 
>>> pstats.Stats("simple-io.cprofile").sort_stats('cumulative').print_stats() 

дает мне много информации Cprofile ... но моя игрушка программа была слишком мала, чтобы дать мне что-нибудь полезное.

+0

Мой 'mpiexec' (1.10.2 от менеджера пакетов Ubuntu 16.04) похоже, не имеет переключателя '-l'. Без него я получаю только один выходной файл, очевидно, для ранга 0. Учитывая, что моя установка более новая, чем ваш ответ, может быть, ваш ответ устарел? – NichtJens

+0

Спасибо. 1.10.2 поступает из OpenMPI. Я обновил свой ответ, чтобы понять, что способ получить ранжирование впереди - это конкретная реализация и документировать две основные реализации. –

+0

Отлично. Немного странно, что, по-видимому, стандартизированный 'mpiexec' делает это таким непоследовательным образом. Я думал, что его целью было заменить «mpirun», который страдает именно от этих несоответствий из-за того, что они не стандартизированы ... – NichtJens

2

Как Rob Latham сказал, что вы можете использовать cProfile. Вы можете сохранить вывод из каждого процесса в другом файле. Если вы хотите, чтобы профилировать функцию можно использовать декоратор, как это:

from mpi4py import MPI 
import cProfile 

def profile(filename=None, comm=MPI.COMM_WORLD): 
    def prof_decorator(f): 
    def wrap_f(*args, **kwargs): 
     pr = cProfile.Profile() 
     pr.enable() 
     result = f(*args, **kwargs) 
     pr.disable() 

     if filename is None: 
     pr.print_stats() 
     else: 
     filename_r = filename + ".{}".format(comm.rank) 
     pr.dump_stats(filename_r) 

     return result 
    return wrap_f 
    return prof_decorator 

@profile(filename="profile_out") 
def my_function(): 
    # do something 

Выход каждого процесса можно визуализировать с помощью snakeviz

+0

Есть ли причина для 'import cProfile' в самой внутренней функции? Таким образом, он каждый раз повторно импортируется ... – NichtJens

+0

Согласно [this] (https://stackoverflow.com/a/3095124/6756219) импорт кэшируется и импортируется только один раз. Тем не менее, нет причин сохранять импорт в самой внутренней функции, поэтому вы можете импортировать его на верхнем уровне. – hnfl

+0

Да, вы правы. Я забыл, что нет никакого штрафа за повторный импорт. Тем не менее, это не обычный стиль ... Кроме того, было бы неплохо добавить строку импорта для singleton MPI, чтобы завершить код. EDIT: Я предложил изменить это. – NichtJens