2008-11-30 4 views
100

У меня есть программа MPI, которая компилируется и запускается, но я хотел бы пройти через нее, чтобы убедиться, что ничего странного не происходит. В идеале, я хотел бы просто подключить GDB к любому конкретному процессу, но я не уверен, что это возможно или как это сделать. Альтернативой будет каждый процесс записи отладки вывода в отдельный файл журнала, но на самом деле это не дает такой же свободы, как отладчик.Как отладить программу MPI?

Есть ли лучшие подходы? Как вы отлаживаете программы MPI?

ответ

48

Как кто-то сказал, TotalView является стандартом для этого. Но это будет стоить вам руки и ноги.

Сайт OpenMPI имеет отличный FAQ on MPI debugging. В пункте № 6 раздела «Часто задаваемые вопросы» описывается, как подключать процессы GDB к MPI. Прочитайте все, есть отличные советы.

Если вы обнаружите, что у вас слишком много процессов, чтобы отслеживать, проверьте Stack Trace Analysis Tool (STAT). Мы используем это в Ливерморе, чтобы собирать трассировки стека из потенциально сотен тысяч запущенных процессов и представлять их разумно для пользователей. Это не полнофункциональный отладчик (полнофункциональный отладчик никогда не масштабируется до 208k ядер), но он расскажет вам, какие группы процессов делают то же самое. Затем вы можете вывести представителя из каждой группы в стандартный отладчик.

+10

Начиная с 2010 года [Allinea DDT] (http://www.olcf.ornl.gov/2010/07/12/upgrade-adds-muscle-to-debugger/) - полнофункциональный отладчик, который масштабируется до 208k ядер – Mark 2012-05-31 12:00:10

+0

Итак, я продолжу и поддержу @ ответ Марка. ДДТ хорош. Попробуйте тоже. TotalView теперь также интегрируется с STAT, поэтому, если ваш сайт имеет установку TotalView, вы также можете попробовать это. LLNL поддерживает TotalView и DDT, и хорошо, что TotalView, наконец, имеет жесткую конкуренцию. – tgamblin 2012-06-07 00:13:27

+0

Я хотел бы добавить ссылку на FAQ по отладке MPI (http://www.open-mpi.org/faq/?category=debugging#serial-debuggers). В частности, bullet 6 является хорошим, быстрым и легким (достаточно даже для меня!), Чтобы понять способ, по крайней мере, отладить отдельный процесс. – Jeff 2012-08-19 18:30:26

3

«Стандартный» способ отладки программ MPI - это использование отладчика, который поддерживает эту модель исполнения.

В UNIX TotalView, как утверждается, имеет хороший Suppoort для MPI.

5

http://github.com/jimktrains/pgdb/tree/master это утилита, которую я написал, чтобы сделать это очень. Есть несколько документов и не стесняйтесь меня на вопросы.

Вы в основном называете программу perl, которая обертывает GDB и выполняет его перемычку на центральный сервер. Это позволяет GDB запускаться на каждом хосте и получать доступ к нему на каждом хосте на терминале.

+0

Спасибо! Я обязательно проверю это в следующий раз, когда я работаю в MPI. – 2009-04-09 03:45:27

1

Я использую этот небольшой метод homebrewn для присоединения отладчика к процессам MPI - вызовите следующую функцию DebugWait(), сразу после MPI_Init() в вашем коде. Теперь, пока процессы ждут ввода с клавиатуры, вы все время присоединяете к ним отладчик и добавляете контрольные точки. Когда вы закончите, укажите один ввод символов, и вы готовы к работе.

static void DebugWait(int rank) { 
    char a; 

    if(rank == 0) { 
     scanf("%c", &a); 
     printf("%d: Starting now\n", rank); 
    } 

    MPI_Bcast(&a, 1, MPI_BYTE, 0, MPI_COMM_WORLD); 
    printf("%d: Starting now\n", rank); 
} 

Конечно, вы хотели бы скомпилировать эту функцию только для отладочных сборников.

+0

MPI потребовал от большинства отладочных инструкций, которые я когда-либо писал для простого кода. (lol) Это может быть очень полезно. – Troggy 2009-07-02 16:38:54

+2

Это решение похоже на пулю 6 здесь (http://www.open-mpi.org/faq/?category=debugging#serial-debuggers). Вы можете немного улучшить свой код, добавив `gethostname (имя хоста, sizeof (имя хоста)); printf («PID% d на хосте% s готов для присоединения \ n», getpid(), имя хоста); `. Затем вы присоединяетесь к процессу, набрав `rsh <имя_файла_from_print_statement>` и, наконец, `gdb -pid = `. – Jeff 2012-08-19 18:35:32

1

Я делаю некоторые отладки, связанные с MPI, с трассировкой журнала, но вы также можете запустить gdb, если вы используете mpich2: MPICH2 and gdb. Этот метод является хорошей практикой в ​​целом, когда вы имеете дело с процессом, который сложно запускать из отладчика.

+0

Ссылка не работает. – 2015-11-21 02:08:49

2

Существует также мой инструмент с открытым исходным кодом, padb, который призван помочь в параллельном программировании. Я называю это «Инструментом осмотра работы», поскольку он функционирует не только потому, что отладчик также может функционировать, например, как параллельная программа, подобная вершине. Запустив режим «Полный отчет», он покажет вам стековые следы каждого процесса в вашем приложении вместе с локальными переменными для каждой функции над каждым рангом (при условии, что вы скомпилированы с -g). Он также покажет вам «очереди сообщений MPI», то есть список выдающихся отправлений и получения для каждого ранга в задании.

Как и при показе полного отчета, можно также указывать padb для увеличения отдельных бит информации в задании, имеется множество опций и элементов конфигурации, чтобы контролировать, какая информация отображается, см. Веб-страницу для более подробно.

Padb

62

Я нашел GDB весьма полезным. Я использую его в качестве

mpirun -np <NP> xterm -e gdb ./program 

это пуски XTERM окна, в которых я могу сделать

run <arg1> <arg2> ... <argN> 

обычно работают прекрасные

Вы также можете упаковать эти команды вместе с использованием:

mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...] 
1

Команда присоединить GDB к процессу МПИ является неполным, он должен быть

mpirun -np <NP> xterm -e gdb ./program 

Краткое обсуждение ПИЛ и БГД можно найти here

16

Как уже упоминалось, если вы работаете только с несколькими процессами MPI, вы можете попробовать использовать multiple gdb sessions, redoubtable valgrind или сканирование собственного решения printf/logging.

Если вы используете больше процессов, чем это, вы действительно начинаете нуждаться в надлежащем отладчике. OpenMPI FAQ рекомендует как Allinea DDT, так и TotalView.

Я работаю на Allinea DDT. Это полнофункциональный графический исходный код отладчик да так, вы можете:

  • Debug или прикрепить (более 200k) MPI процессов
  • шаг и приостановить их в группах или индивидуально
  • Добавить контрольные точки, часы и
  • точки трассировки
  • отлавливать ошибки памяти и утечки

... и так далее. Если вы использовали Eclipse или Visual Studio, тогда вы будете дома.

Мы добавили некоторые интересные функции, специально для отладки параллельных кода (будь то MPI, многопоточного или CUDA):

  • Скалярных переменных автоматически сравниваются во всех процессах: Sparklines showing values across processes

  • Вы также можете отслеживать и фильтровать значения переменных и выражений по процессам и времени: Tracepoints log values over time

Он широко используется среди top500 сайтов высокопроизводительных вычислений, таких как ORNL, NCSA, LLNL, Jülich эт. и др.

Интерфейс довольно быстрый; мы приурочили постепенное и слияние стеков и переменных 220 000 процессов в 0,1 с в рамках приемочных испытаний на кластере Jaguar Oak Ridge.

@tgamblin отметил отличный STAT, который интегрируется с Allinea DDT, а также некоторые другие популярные проекты с открытым исходным кодом.

17

Многие из постов здесь около GDB, но не говоря уже о том, как подключиться к процессу с момента запуска. Очевидно, что вы можете прикрепить ко всем процессам:

mpiexec -n X gdb ./a.out 

Но это дико неэффективно, так как вам придется подпрыгивать вокруг, чтобы начать все ваши процессы. Если вы просто хотите отладить один (или небольшое количество) процесса MPI, можно добавить, что в качестве отдельного исполняемого файла в командной строке с помощью : оператора:

mpiexec -n 1 gdb ./a.out : -n X-1 ./a.out 

Теперь только один из ваших процессов получат GDB ,

4

Использование screen вместе с gdb для отладки приложений MPI прекрасно работает, особенно если xterm недоступен или вы имеете дело с несколькими процессорами. Было много подводных камней на пути с сопровождением поиска stackoverflow, поэтому я полностью воспроизведу свое решение.

Сначала добавьте код после MPI_Init, чтобы распечатать PID и остановить программу, чтобы дождаться, когда вы ее подключите. Стандартное решение кажется бесконечным циклом; В конце концов я остановился на raise(SIGSTOP);, что требует дополнительного звонка continue, чтобы сбежать внутри gdb.

} 
    int i, id, nid; 
    MPI_Comm_rank(MPI_COMM_WORLD,&id); 
    MPI_Comm_size(MPI_COMM_WORLD,&nid); 
    for (i=0; i<nid; i++) { 
     MPI_Barrier(MPI_COMM_WORLD); 
     if (i==id) { 
      fprintf(stderr,"PID %d rank %d\n",getpid(),id); 
     } 
     MPI_Barrier(MPI_COMM_WORLD); 
    } 
    raise(SIGSTOP); 
} 

После компиляции запустите исполняемый файл в фоновом режиме и поймайте stderr. Затем вы можете указать grep файл stderr для некоторого ключевого слова (здесь буквальный PID), чтобы получить PID и ранг каждого процесса.

MDRUN_EXE=../../Your/Path/To/bin/executable 
MDRUN_ARG="-a arg1 -f file1 -e etc" 

mpiexec -n 1 $MDRUN_EXE $MDRUN_ARG >> output 2>> error & 

sleep 2 

PIDFILE=pid.dat 
grep PID error > $PIDFILE 
PIDs=(`awk '{print $2}' $PIDFILE`) 
RANKs=(`awk '{print $4}' $PIDFILE`) 

сеанса GDB может быть присоединен к каждому процессу с gdb $MDRUN_EXE $PID. Выполнение этого в сеансе экрана позволяет легко получить доступ к любому сеансу gdb.-d -m запускает экран в отдельном режиме, -S "P$RANK" позволяет вам назвать экран для легкого доступа позже, а опция -l для bash запускает его в интерактивном режиме и немедленно отключает gdb.

for i in `awk 'BEGIN {for (i=0;i<'${#PIDs[@]}';i++) {print i}}'` 
do 
    PID=${PIDs[$i]} 
    RANK=${RANKs[$i]} 
    screen -d -m -S "P$RANK" bash -l -c "gdb $MDRUN_EXE $PID" 
done 

После того, как GDB начал в экранах, вы можете ввести скрипт на экраны (так что вам не придется вводить каждый экран и введите то же самое), используя команду -X stuff экрана. В конце команды требуется новая строка. Здесь к экранам обращаются -S "P$i" с использованием названий, ранее указанных. Опция -p 0 имеет решающее значение, иначе команда прерывается с ошибкой (в зависимости от того, была ли вы ранее прикреплена к экрану).

for i in `awk 'BEGIN {for (i=0;i<'${#PIDs[@]}';i++) {print i}}'` 
do 
    screen -S "P$i" -p 0 -X stuff "set logging file debug.$i.log 
" 
    screen -S "P$i" -p 0 -X stuff "set logging overwrite on 
" 
    screen -S "P$i" -p 0 -X stuff "set logging on 
" 
    screen -S "P$i" -p 0 -X stuff "source debug.init 
" 
done 

На данный момент вы можете прикрепить к любому экрану с помощью screen -rS "P$i" и отделяться с помощью Ctrl+A+D. Команды могут быть отправлены на все сеансы gdb аналогично предыдущему разделу кода.

0

Другое решение - запустить ваш код в SMPI, моделируемый MPI. Это проект с открытым исходным кодом, в котором я участвую. Каждый ранг MPI будет преобразован в потоки одного и того же процесса UNIX. Затем вы можете легко использовать gdb для установки рангов MPI.

SMPI предлагает другие преимущества для изучения приложений MPI: clairevoyance (вы можете наблюдать за каждой частью системы), воспроизводимость (несколько прогонов приводят к точному поведению, если вы не указали это), отсутствие heisenbugs (в качестве моделируемого платформа поддерживается отличной от основной) и т. д.

Для получения дополнительной информации см. this presentation или что related answer.

0

Если вы tmux пользователя вы будете чувствовать себя очень комфортно, используя сценарий Бенедикт Морбаха: tmpi

https://github.com/moben/scripts/blob/master/tmpi

С его помощью у вас есть несколько панелей (количество процессов) все синхронизированных (каждая команда копируется на все панели или процессы одновременно, поэтому вы сохраняете много времени по сравнению с подходом xterm -e). Кроме того, вы можете знать значения переменных в процессе, который вы хотите просто сделать print, не переходя на другую панель, это будет печатать на каждой панели значения переменной для каждого процесса.

Если вы не являетесь пользователем tmux, я настоятельно рекомендую его попробовать и посмотреть.

Смежные вопросы