Menggunakan screen
bersama-sama gdb
untuk men-debug aplikasi MPI berfungsi dengan baik, terutama jika xterm
tidak tersedia atau Anda berurusan dengan lebih dari beberapa prosesor. Ada banyak jebakan di sepanjang jalan dengan menyertai pencarian stackoverflow, jadi saya akan mereproduksi solusi saya sepenuhnya.
Pertama, tambahkan kode setelah MPI_Init untuk mencetak PID dan menghentikan program untuk menunggu Anda melampirkan. Solusi standar tampaknya merupakan infinite loop; Saya akhirnya memutuskan raise(SIGSTOP);
, yang membutuhkan panggilan ekstra continue
untuk melarikan diri dalam 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);
}
Setelah mengkompilasi, jalankan executable di latar belakang, dan tangkap stderr. Anda kemudian dapat grep
file stderr untuk beberapa kata kunci (di sini PID harfiah) untuk mendapatkan PID dan peringkat dari setiap proses.
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`)
Sesi gdb dapat dilampirkan ke setiap proses dengan gdb $MDRUN_EXE $PID
. Melakukannya dalam sesi layar memungkinkan akses mudah ke sesi gdb. -d -m
memulai layar dalam mode terpisah, -S "P$RANK"
memungkinkan Anda memberi nama layar untuk akses mudah nanti, dan -l
opsi untuk mem-bash memulai dalam mode interaktif dan menjaga gdb agar tidak segera keluar.
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
Setelah gdb dimulai di layar, Anda dapat memasukkan input ke layar (sehingga Anda tidak harus masuk ke setiap layar dan mengetik hal yang sama) menggunakan -X stuff
perintah layar . Baris baru diperlukan di akhir perintah. Di sini layar diakses dengan -S "P$i"
menggunakan nama yang diberikan sebelumnya. The -p 0
pilihan adalah penting, jika perintah sebentar-sebentar gagal (berdasarkan pada apakah atau tidak Anda sebelumnya telah melekat pada layar).
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
Pada titik ini Anda dapat melampirkan ke layar apa pun menggunakan screen -rS "P$i"
dan melepaskan menggunakan Ctrl+A+D
. Perintah dapat dikirim ke semua sesi gdb dalam analogi dengan bagian kode sebelumnya.