Bagaimana cara saya debug program MPI?

129

Saya memiliki program MPI yang mengkompilasi dan menjalankan, tetapi saya ingin melangkah melaluinya untuk memastikan tidak ada yang aneh yang terjadi. Idealnya, saya ingin cara sederhana untuk melampirkan GDB ke proses tertentu, tapi saya tidak begitu yakin apakah itu mungkin atau bagaimana melakukannya. Sebuah alternatif akan meminta setiap proses menulis hasil debug ke file log yang terpisah, tetapi ini tidak benar-benar memberikan kebebasan yang sama dengan debugger.

Apakah ada pendekatan yang lebih baik? Bagaimana Anda men-debug program MPI?

Jay Conrod
sumber

Jawaban:

62

Seperti orang lain katakan, TotalView adalah standar untuk ini. Tetapi akan dikenakan biaya lengan dan kaki.

Situs OpenMPI memiliki FAQ yang bagus tentang debugging MPI . Item # 6 di FAQ menjelaskan cara melampirkan GDB ke proses MPI. Baca semuanya, ada beberapa tips hebat.

Jika Anda menemukan bahwa Anda memiliki terlalu banyak proses untuk dilacak, periksa Alat Analisis Jejak Stack (STAT) . Kami menggunakan ini di Livermore untuk mengumpulkan jejak tumpukan dari ratusan ribu proses yang berjalan dan untuk mewakilinya secara cerdas kepada pengguna. Ini bukan debugger berfitur lengkap (debugger berfitur lengkap tidak akan pernah menskala menjadi 208k core), tetapi akan memberi tahu Anda kelompok proses mana yang melakukan hal yang sama. Anda kemudian dapat melangkah melalui perwakilan dari setiap grup dalam debugger standar.

Todd Gamblin
sumber
14
Pada 2010 Allinea DDT adalah debugger berfitur lengkap yang menskala hingga lebih dari 208k core
Tandai
1
Jadi saya akan melanjutkan dan menjawab jawaban @ Mark di sini. DDT itu bagus. Cobalah juga. TotalView juga terintegrasi dengan STAT sekarang, jadi jika situs Anda memiliki instalasi TotalView, Anda dapat mencobanya juga. LLNL menjaga TotalView dan DDT tetap ada, dan senang bahwa TotalView akhirnya memiliki persaingan yang ketat.
Todd Gamblin
Saya ingin memberi tautan kedua pada FAQ tentang debugging MPI ( open-mpi.org/faq/?category=debugging#serial-debuggers ). Secara khusus, peluru 6 adalah cara yang baik, cepat, dan mudah (cukup bahkan untuk saya!) Untuk memahami cara setidaknya men-debug proses individu.
Jeff
Langkah-langkah di # 6 dari halaman FAQ bekerja dengan baik untuk saya dan membantu saya memecahkan masalah saya. Terima kasih banyak atas ini.
Jon Deaton
86

Saya menemukan gdb cukup bermanfaat. Saya menggunakannya sebagai

mpirun -np <NP> xterm -e gdb ./program 

Ini meluncurkan windows xterm yang bisa saya lakukan

run <arg1> <arg2> ... <argN>

biasanya berfungsi dengan baik

Anda juga dapat mengemas perintah-perintah ini bersama-sama menggunakan:

mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]
messenjah
sumber
Bagaimana saya bisa mengirim input yang sama ke semua xterms gdb NP? Sebagai contoh, saya ingin menambahkan dua breakpoint ke setiap proses, dan ada 16 proses. Apakah ada alternatif untuk xterm untuk melakukan ini? Bisakah kita menghubungkan sesi ke instance layar, tmux, atau Terminator Chris Jones?
osgx
@osgx Anda dapat melakukan ini dengan menyimpan perintah ("break xxx", "break yyy", "run") ke <file>dan meneruskan -x <file>ke gdb.
eush77
tapi saya menemukan kesalahan, pesan kesalahan adalah "kesalahan execvp pada file xterm (Tidak ada file atau direktori seperti itu)"
hitwlh
ketika saya mencoba ini dengan jdb & OpenMPI tidak berfungsi, yaitu setiap instance jdb melihat num_ranks dari 1 bukannya apa yang diberikan pada argumen -np. ada yang tahu kenapa?
Michel Müller
26

Banyak posting di sini tentang GDB, tetapi tidak menyebutkan cara melampirkan proses dari startup. Jelas, Anda dapat melampirkan ke semua proses:

mpiexec -n X gdb ./a.out

Tapi itu sangat tidak efektif karena Anda harus bangkit untuk memulai semua proses Anda. Jika Anda hanya ingin men-debug satu (atau sejumlah kecil) proses MPI, Anda dapat menambahkan itu sebagai executable terpisah pada baris perintah menggunakan :operator:

mpiexec -n 1 gdb ./a.out : -n X-1 ./a.out

Sekarang hanya satu dari proses Anda yang akan mendapatkan GDB.

Wesley Bland
sumber
Saya dapat menggunakan "mpiexec -n X gdb ./a.out", tetapi apakah ada cara untuk menggunakan mode gdb -tui?
hitwlh
16

Seperti yang disebutkan orang lain, jika Anda hanya bekerja dengan beberapa proses MPI, Anda dapat mencoba menggunakan beberapa sesi gdb , valgrind yang dapat dipertanyakan atau memutar solusi printf / logging Anda sendiri.

Jika Anda menggunakan lebih banyak proses dari itu, Anda benar-benar mulai membutuhkan debugger yang tepat. The openmpi FAQ merekomendasikan baik Allinea DDT dan TotalView .

Saya bekerja di Allinea DDT . Ini adalah debugger kode sumber grafis berfitur lengkap, jadi ya, Anda dapat:

  • Debug atau lampirkan ke (lebih dari 200k) proses MPI
  • Langkah dan jeda mereka dalam kelompok atau secara individual
  • Tambahkan breakpoints, jam tangan dan tracepoint
  • Menangkap kesalahan memori dan kebocoran

...dan seterusnya. Jika Anda menggunakan Eclipse atau Visual Studio maka Anda akan betah.

Kami menambahkan beberapa fitur menarik khusus untuk debugging kode paralel (baik itu MPI, multi-threaded atau CUDA):

  • Variabel skalar secara otomatis dibandingkan di semua proses: (sumber: allinea.com )Grafik mini menunjukkan nilai di seluruh proses

  • Anda juga dapat melacak dan memfilter nilai-nilai variabel dan ekspresi selama proses dan waktu: Nilai log titik tracepoint dari waktu ke waktu

Ini banyak digunakan di antara 500 situs HPC teratas , seperti ORNL , NCSA , LLNL , Jülich et. Al.

Antarmukanya cukup tajam; kami menghitung waktu melangkah dan menggabungkan tumpukan dan variabel dari 220.000 proses pada 0,1 sebagai bagian dari pengujian penerimaan pada kelompok Jaguar Oak Ridge.

@tgamblin menyebutkan STAT yang luar biasa , yang terintegrasi dengan Allinea DDT , seperti halnya beberapa proyek open source populer lainnya.

Menandai
sumber
7

Jika Anda seorang tmuxpengguna, Anda akan merasa sangat nyaman menggunakan skrip Benedikt Morbach :tmpi

Sumber asli: https://github.com/moben/scripts/blob/master/tmpi

Fork: https://github.com/Azrael3000/tmpi

Dengannya Anda memiliki beberapa panel (jumlah proses) yang semuanya disinkronkan (setiap perintah disalin pada semua panel atau proses pada saat yang sama sehingga Anda menghemat banyak waktu dibandingkan dengan xterm -ependekatannya). Selain itu Anda dapat mengetahui nilai-nilai variabel dalam proses yang Anda inginkan hanya melakukan printtanpa harus pindah ke panel lain, ini akan mencetak pada setiap panel nilai-nilai variabel untuk setiap proses.

Jika Anda bukan tmuxpengguna, saya sangat merekomendasikan untuk mencobanya dan melihatnya.

GG1991
sumber
2
Karena tmpi benar-benar fantastis dan persis apa yang saya cari, saya memotongnya di akun github saya: github.com/Azrael3000/tmpi sejak penulis asli menghapusnya
Azrael3000
6

http://github.com/jimktrains/pgdb/tree/master adalah utilitas yang saya tulis untuk melakukan hal ini. Ada beberapa dokumen dan jangan ragu untuk bertanya kepada saya.

Anda pada dasarnya memanggil program perl yang membungkus GDB dan saluran itu IO ke server pusat. Ini memungkinkan GDB dijalankan pada setiap host dan bagi Anda untuk mengaksesnya pada setiap host di terminal.

Jim Keener
sumber
Terima kasih! Saya pasti akan memeriksa ini waktu berikutnya saya bekerja di MPI.
Jay Conrod
5

Menggunakan screenbersama-sama gdbuntuk men-debug aplikasi MPI berfungsi dengan baik, terutama jika xtermtidak 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 continueuntuk 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 grepfile 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 -mmemulai layar dalam mode terpisah, -S "P$RANK"memungkinkan Anda memberi nama layar untuk akses mudah nanti, dan -lopsi 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 stuffperintah layar . Baris baru diperlukan di akhir perintah. Di sini layar diakses dengan -S "P$i"menggunakan nama yang diberikan sebelumnya. The -p 0pilihan 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.

pengguna3788566
sumber
3

Ada juga alat open-source saya, padb, yang bertujuan untuk membantu pemrograman paralel. Saya menyebutnya "Alat Inspeksi Pekerjaan" karena berfungsi tidak hanya sebagai debugger juga dapat berfungsi misalnya sebagai program seperti paralel atas. Jalankan dalam mode "Laporan Lengkap" itu akan menunjukkan Anda menumpuk jejak setiap proses dalam aplikasi Anda bersama dengan variabel lokal untuk setiap fungsi di setiap peringkat (dengan asumsi Anda dikompilasi dengan -g). Ini juga akan menunjukkan "antrian pesan MPI", yaitu daftar pengiriman dan penerimaan luar biasa untuk setiap peringkat dalam pekerjaan tersebut.

Selain menunjukkan laporan lengkap, Anda juga dapat memberi tahu padb untuk memperbesar setiap bit informasi dalam pekerjaan, ada banyak opsi dan item konfigurasi untuk mengontrol informasi apa yang ditampilkan, lihat halaman web untuk lebih jelasnya.

Padb


sumber
3

Cara "standar" untuk men-debug program MPI adalah dengan menggunakan debugger yang mendukung model eksekusi itu.

Di UNIX, TotalView dikatakan memiliki penunjang yang bagus untuk MPI.

Komunitas
sumber
2

Saya menggunakan metode homebrewn kecil ini untuk melampirkan debugger ke proses MPI - panggil fungsi berikut, DebugWait (), tepat setelah MPI_Init () dalam kode Anda. Sekarang saat proses sedang menunggu input keyboard, Anda memiliki semua waktu untuk melampirkan debugger ke sana dan menambahkan breakpoints. Setelah selesai, berikan input karakter tunggal dan Anda siap untuk pergi.

static void DebugWait(int rank) {
    char    a;

    if(rank == 0) {
        scanf("%c", &a);
        printf("%d: Starting now\n", rank);
    } 

    MPI_Bcast(&a, 1, MPI_BYTE, 0, MPI_COMM_WORLD);
    printf("%d: Starting now\n", rank);
}

Tentu saja Anda ingin mengkompilasi fungsi ini hanya untuk debug build.


sumber
MPI telah membutuhkan pernyataan debug paling banyak yang pernah saya tulis untuk kode sederhana sekalipun. (lol) Ini bisa sangat membantu.
Troggy
3
Solusi ini mirip dengan bullet 6 di sini ( open-mpi.org/faq/?category=debugging#serial-debuggers ). Anda dapat sedikit meningkatkan kode Anda dengan menambahkan gethostname(hostname, sizeof(hostname)); printf("PID %d on host %s ready for attach\n", getpid(), hostname);. Lalu, Anda lampirkan ke proses dengan mengetik rsh <hostname_from_print_statement>, dan akhirnya gdb --pid=<PID_from_print_statement>.
Jeff
2

Perintah untuk melampirkan gdb ke proses mpi tidak lengkap, seharusnya

mpirun -np <NP> xterm -e gdb ./program 

Diskusi singkat tentang mpi dan gdb dapat ditemukan di sini

akintayo
sumber
2

Cara yang cukup sederhana untuk men-debug program MPI.

Di main () fungsi tambah sleep (some_seconds)

Jalankan program seperti biasa

$ mpirun -np <num_of_proc> <prog> <prog_args>

Program akan dimulai dan mulai tidur.

Jadi Anda akan memiliki beberapa detik untuk menemukan proses Anda oleh ps, jalankan gdb dan lampirkan padanya.

Jika Anda menggunakan beberapa editor seperti QtCreator, Anda dapat menggunakannya

Debug-> Mulai debugging-> Lampirkan untuk menjalankan aplikasi

dan menemukan Anda proses di sana.

orang asing
sumber
1

Saya melakukan beberapa debug terkait MPI dengan jejak log, tetapi Anda juga dapat menjalankan gdb jika Anda menggunakan mpich2: MPICH2 dan gdb . Teknik ini adalah praktik yang baik secara umum ketika Anda berurusan dengan proses yang sulit untuk memulai dari debugger.

Jim Hunziker
sumber
Diubah ke tautan lain yang tidak rusak, tambah beberapa komentar.
Jim Hunziker
0

Solusi lain adalah menjalankan kode Anda dalam SMPI, MPI yang disimulasikan. Itu proyek sumber terbuka di mana saya terlibat. Setiap peringkat MPI akan dikonversi menjadi utas dari proses UNIX yang sama. Anda kemudian dapat dengan mudah menggunakan gdb untuk melangkah ke peringkat MPI.

SMPI mengusulkan keuntungan lain untuk mempelajari aplikasi MPI: clairevoyance (Anda dapat mengamati setiap bagian dari sistem), reproduktifitas (beberapa run mengarah ke perilaku yang sama persis kecuali Anda tentukan demikian), tidak adanya heisenbug (karena platform yang disimulasikan tetap berbeda dari host satu), dll.

Untuk informasi lebih lanjut, lihat presentasi ini , atau jawaban terkait itu .

Martin Quinson
sumber