Использование 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 запустился на экранах, вы можете выполнить ввод сценария для экранов (чтобы вам не приходилось вводить каждый экран и вводить одно и то же) с помощью команды screen -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 по аналогии с предыдущим разделом кода.