Використання screen
разом із gdb
налагодженням програм MPI прекрасно працює, особливо якщо xterm
він недоступний або ви маєте справу з декількома процесорами. Попутно було багато підводних каменів із супутніми пошуковими потоками, тому я відтворять своє рішення в повному обсязі.
По-перше, додайте код після 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 за аналогією з попереднім розділом коду.