Использование 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 по аналогии с предыдущим разделом кода.
person
user3788566
schedule
29.06.2014