Việc sử dụng screen
cùng với gdb
để gỡ lỗi các ứng dụng MPI hoạt động độc đáo, đặc biệt là nếu xterm
không có sẵn hoặc bạn đang xử lý nhiều hơn một vài bộ xử lý. Có rất nhiều cạm bẫy trên đường đi với các tìm kiếm stackoverflow đi kèm, vì vậy tôi sẽ tái tạo đầy đủ giải pháp của mình.
Đầu tiên, thêm mã sau MPI_Init để in ra PID và tạm dừng chương trình để chờ bạn đính kèm. Các giải pháp tiêu chuẩn dường như là một vòng lặp vô hạn; Cuối cùng tôi đã giải quyết raise(SIGSTOP);
, đòi hỏi một cuộc gọi thêm continue
để thoát trong 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);
}
Sau khi biên dịch, chạy chương trình thực thi trong nền và bắt stderr. Sau đó, bạn có thể grep
gửi tệp stderr cho một số từ khóa (ở đây là chữ viết tắt) để có được PID và thứ hạng của mỗi quá trình.
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`)
Một phiên gdb có thể được đính kèm với mỗi quá trình với gdb $MDRUN_EXE $PID
. Làm như vậy trong một phiên màn hình cho phép dễ dàng truy cập vào bất kỳ phiên gdb nào. -d -m
khởi động màn hình ở chế độ tách rời, -S "P$RANK"
cho phép bạn đặt tên cho màn hình để dễ dàng truy cập sau và -l
tùy chọn bash khởi động màn hình ở chế độ tương tác và giữ cho gdb không thoát ra ngay lập tức.
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
Khi gdb đã bắt đầu trong màn hình, bạn có thể nhập kịch bản vào màn hình (để bạn không phải nhập mọi màn hình và nhập cùng một thứ) bằng cách sử dụng -X stuff
lệnh của màn hình . Một dòng mới được yêu cầu ở cuối lệnh. Ở đây các màn hình được truy cập bằng -S "P$i"
cách sử dụng các tên được đưa ra trước đó. Các -p 0
tùy chọn là rất quan trọng, nếu không lệnh liên tục thất bại (dựa trên hay không trước đó bạn đã gắn liền với màn hình).
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
Tại thời điểm này, bạn có thể gắn vào bất kỳ màn hình nào bằng cách sử dụng screen -rS "P$i"
và tháo ra bằng cách sử dụng Ctrl+A+D
. Các lệnh có thể được gửi đến tất cả các phiên gdb tương tự với phần mã trước đó.