Bir MPI programında nasıl hata ayıklayabilirim?


129

Derleyen ve çalışan bir MPI programım var, ancak tuhaf bir şey olmadığından emin olmak için adım adım ilerlemek istiyorum. İdeal olarak, GDB'yi belirli bir sürece eklemenin basit bir yolunu isterim, ancak bunun mümkün olup olmadığından veya nasıl yapılacağından emin değilim. Bir alternatif, her işlemin hata ayıklama çıktısını ayrı bir günlük dosyasına yazması olabilir, ancak bu gerçekten bir hata ayıklayıcı ile aynı özgürlüğü vermez.

Daha iyi yaklaşımlar var mı? MPI programlarında nasıl hata ayıklayabilirsiniz?

Yanıtlar:


62

Başka birinin söylediği gibi, TotalView bunun için standarttır. Ama sana bir kola ve bacağa mal olacak.

OpenMPI sitesinde MPI hata ayıklamayla ilgili harika bir SSS bulunur . SSS'deki Madde 6, GDB'nin MPI süreçlerine nasıl ekleneceğini açıklar. Her şeyi okuyun, bazı harika ipuçları var.

Takip etmeniz gereken çok fazla işleminiz olduğunu fark ederseniz, Yığın İzleme Analiz Aracı'na (STAT) göz atın . Bunu Livermore'da potansiyel olarak yüz binlerce çalışan süreçten yığın izleri toplamak ve bunları kullanıcılara akıllıca sunmak için kullanıyoruz. Tam özellikli bir hata ayıklayıcı değildir (tam özellikli bir hata ayıklayıcı asla 208k çekirdeğe ölçeklenmez), ancak hangi işlem gruplarının aynı şeyi yaptığını size söyleyecektir. Daha sonra, standart bir hata ayıklayıcıda her gruptan bir temsilcinin üzerinden geçebilirsiniz.


14
2010 itibariyle Allinea DDT , 208.000'den fazla çekirdeğe ölçeklenen tam özellikli bir hata ayıklayıcıdır
Mark

1
Bu yüzden devam edip @ Mark'ın cevabını burada yükselteceğim. DDT güzeldir. Siz de deneyin. TotalView ayrıca artık STAT ile entegre olur, bu nedenle sitenizde bir TotalView kurulumu varsa bunu da deneyebilirsiniz. LLNL, TotalView ve DDT'yi etrafta tutuyor ve TotalView'ın nihayet sert bir rekabete sahip olması güzel.
Todd Gamblin

MPI hata ayıklamayla ilgili SSS bağlantısını ikinci kez yapmak istiyorum ( open-mpi.org/faq/?category=debugging#serial-debuggers ). Özellikle, madde 6 en azından bireysel bir süreçte hata ayıklamanın iyi, hızlı ve kolay (benim için bile yeterli!) Bir yoludur.
Jeff

SSS sayfasının 6. adımında benim için mükemmel çalıştı ve sorunumu çözmeme yardımcı oldu. Bunun için çok teşekkürler.
Jon Deaton

86

Gdb'yi oldukça kullanışlı buldum. Olarak kullanıyorum

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

Bu, yapabileceğim xterm pencerelerini başlatıyor

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

genellikle iyi çalışır

Aşağıdaki komutları kullanarak da bu komutları paketleyebilirsiniz:

mpirun -n <NP> xterm -hold -e gdb -ex run --args ./program [arg1] [arg2] [...]

Aynı girdiyi tüm NP gdb xterms'e nasıl gönderebilirim? Örneğin, her işleme iki kesme noktası eklemek istiyorum ve 16 işlem var. Bunu yapmak için xterm'e alternatif var mı? Oturumları tek bir ekran, tmux veya Chris Jones'un Terminatörüne bağlayabilir miyiz?
osgx

@osgx Bunu, komutları ("xxx kır", "yyy kes", "çalıştır") kaydedip gdb'ye <file>ileterek yapabilirsiniz -x <file>.
eush77

ancak bir hatayla karşılaşıyorum, hata mesajı "xterm dosyasında execvp hatası (Böyle bir dosya veya dizin yok)"
hitwlh

bunu jdb & OpenMPI ile denediğimde çalışmıyor, yani her jdb örneği -np argümanına verilenin yerine 1'in num_ranks'ını görüyor. herhangi bir fikriniz neden?
Michel Müller

26

Buradaki yayınların çoğu GDB hakkındadır, ancak başlangıçtan itibaren bir sürece nasıl ekleneceğinden bahsetmeyin. Açıkçası, tüm süreçlere ekleyebilirsiniz:

mpiexec -n X gdb ./a.out

Ancak bu, tüm süreçlerinizi başlatmak için zıplamanız gerekeceği için çılgınca etkisizdir. Yalnızca bir (veya az sayıda) MPI işleminde hata ayıklamak istiyorsanız, :operatörü kullanarak bunu komut satırına ayrı bir yürütülebilir dosya olarak ekleyebilirsiniz :

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

Artık süreçlerinizden yalnızca biri GDB'yi alacak.


"Mpiexec -n X gdb ./a.out" kullanabilirim, ancak gdb -tui modunu kullanmanın herhangi bir yolu var mı?
hitwlh

16

Diğerlerinin de belirttiği gibi, yalnızca bir avuç MPI işlemi ile çalışıyorsanız, birden çok gdb oturumunu , yeniden katlanabilen valgrind'i kullanmayı deneyebilir veya kendi printf / logging çözümünüzü oluşturabilirsiniz.

Bundan daha fazla işlem kullanıyorsanız, gerçekten uygun bir hata ayıklayıcıya ihtiyaç duymaya başlarsınız. OpenMPI SSS hem önerir Allinea DDT ve Totalview .

Allinea DDT üzerinde çalışıyorum . Bu tam özellikli, grafiksel bir kaynak kodu hata ayıklayıcısıdır, bu nedenle evet, şunları yapabilirsiniz:

  • MPI işlemlerinde hata ayıklama veya ekleme (200.000'den fazla)
  • Gruplar halinde veya tek tek adımlayın ve duraklatın
  • Kesme noktaları, saatler ve izleme noktaları ekleyin
  • Bellek hatalarını ve sızıntılarını yakalayın

...ve bunun gibi. Eclipse veya Visual Studio kullandıysanız, hemen evde olacaksınız.

Özellikle paralel kodda hata ayıklamak için bazı ilginç özellikler ekledik (MPI, çok iş parçacıklı veya CUDA):

  • Skaler değişkenler tüm süreçlerde otomatik olarak karşılaştırılır: (kaynak: allinea.com )İşlemler arasında değerleri gösteren mini grafikler

  • Ayrıca, değişkenlerin ve ifadelerin değerlerini süreçler ve zaman boyunca izleyebilir ve filtreleyebilirsiniz: Zaman içinde izleme noktaları günlük değerleri

ORNL , NCSA , LLNL , Jülich ve benzeri gibi ilk 500 HPC sitesi arasında yaygın olarak kullanılmaktadır . ark.

Arayüz oldukça hızlıdır; Oak Ridge'in Jaguar kümesindeki kabul testinin bir parçası olarak, 220.000 işlemin yığınlarını ve değişkenlerini 0.1 saniyede adımlamayı ve birleştirmeyi zamanladık.

@tgamblin mükemmel belirtilen STAT ile bütünleşmeler, Allinea DDT gibi diğer bazı popüler açık kaynak projeleri yapmak.



7

Eğer bir iseniz tmuxkullanıcı size komut dosyası kullanarak çok rahat hissedeceksiniz Benedikt Morbach'tan :tmpi

Orjinal kaynak: https://github.com/moben/scripts/blob/master/tmpi

Çatal: https://github.com/Azrael3000/tmpi

Bununla birlikte, hepsi senkronize edilmiş birden fazla panele (işlem sayısı) sahip olursunuz (her komut tüm panellere veya işlemlere aynı anda kopyalanır, böylece xterm -eyaklaşımla karşılaştırıldığında çok zaman kazanırsınız ). Ayrıca print, başka bir panele geçmek zorunda kalmadan, istediğiniz işlemdeki değişkenlerin değerlerini bilebilirsiniz , bu, her bir işlem için değişkenin değerlerini her panele yazdırır.

tmuxKullanıcı değilseniz kesinlikle denemenizi ve görmenizi tavsiye ederim.


2
Tmpi gerçekten harika olduğundan ve tam olarak aradığım şey olduğundan, onu github hesabıma ekledim : github.com/Azrael3000/tmpi orijinal yazar onu kaldırdığından beri
Azrael3000

6

http://github.com/jimktrains/pgdb/tree/master tam da bunu yapmak için yazdığım bir yardımcı program. Bazı dokümanlar var ve soru sormak için bana mesaj atmaktan çekinmeyin.

Temel olarak GDB'yi saran ve IO'yu merkezi bir sunucuya aktaran bir perl programı çağırırsınız. Bu, GDB'nin her ana bilgisayarda çalışmasına ve sizin için terminaldeki her ana bilgisayarda ona erişmenize izin verir.


Teşekkürler! Bir dahaki sefere MPI'de çalıştığımda bunu kesinlikle kontrol edeceğim.
Jay Conrod

5

MPI uygulamalarında hata ayıklamak için screenbirlikte kullanmak gdb, özellikle xtermkullanılamıyorsa veya birkaç işlemciyle uğraşıyorsanız, iyi çalışır. Eşlik eden yığın akışı aramalarında birçok tuzak vardı, bu yüzden çözümümü tam olarak yeniden üreteceğim.

İlk olarak, PID'yi yazdırmak için MPI_Init'ten sonra kod ekleyin ve eklemenizi beklemesi için programı durdurun. Standart çözüm sonsuz bir döngü gibi görünüyor; Sonunda raise(SIGSTOP);, continuegdb içinde kaçmak için fazladan bir çağrı gerektiren bir karar verdim .

}
    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);
}

Derledikten sonra, yürütülebilir dosyayı arka planda çalıştırın ve stderr'i yakalayın. Daha sonra grepher işlemin PID'sini ve sırasını almak için bazı anahtar sözcükler için (burada gerçek PID) stderr dosyasını kullanabilirsiniz .

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`)

İle her işleme bir gdb oturumu eklenebilir gdb $MDRUN_EXE $PID. Bunu bir ekran oturumu içinde yapmak, herhangi bir gdb oturumuna kolay erişim sağlar. -d -mekranı bağımsız modda başlatır, ekranı -S "P$RANK"daha sonra kolay erişim için adlandırmanıza izin verir ve -lbash seçeneği onu etkileşimli modda başlatır ve gdb'nin hemen çıkmasını engeller.

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

Ekranlarda gdb başladığında, ekran -X stuffkomutunu kullanarak ekranlara giriş komut dosyası oluşturabilirsiniz (böylece her ekrana girip aynı şeyi yazmanıza gerek kalmaz) . Komutun sonunda yeni bir satır gereklidir. Burada ekranlara daha -S "P$i"önce verilen isimler kullanılarak ulaşılır . -p 0Seçenek aksi komut aralıklı (Daha önce ekrana bağlı olsun veya olmasın göre) başarısız kritiktir.

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

Bu noktada kullanarak herhangi bir ekrana takabilir ve kullanarak screen -rS "P$i"ayırabilirsiniz Ctrl+A+D. Komutlar, kodun önceki bölümüyle benzer şekilde tüm gdb oturumlarına gönderilebilir.


3

Paralel programlamaya yardımcı olmayı amaçlayan açık kaynak aracım padb de var. Ben buna "İş İnceleme Aracı" diyorum çünkü sadece hata ayıklayıcı olarak değil, örneğin paralel bir üst program gibi de çalışabilir. "Tam Rapor" modunda çalıştırın, size uygulamanızdaki her işlemin yığın izlerini ve her kademedeki her işlev için yerel değişkenleri gösterecektir (-g ile derlediğiniz varsayılarak). Ayrıca size "MPI mesaj kuyruklarını", yani iş içindeki her aşama için bekleyen göndermelerin ve alımların listesini gösterecektir.

Tam raporu göstermenin yanı sıra, padb'e iş içindeki bireysel bilgi bitlerini yakınlaştırmasını söylemek de mümkündür, hangi bilgilerin gösterileceğini kontrol etmek için sayısız seçenek ve yapılandırma öğesi vardır, daha fazla ayrıntı için web sayfasına bakın.

Padb


3

MPI programlarında hata ayıklamanın "standart" yolu, bu yürütme modelini destekleyen bir hata ayıklayıcı kullanmaktır.

UNIX'te, TotalView'ın MPI için iyi bir desteği olduğu söyleniyor.


2

Bu küçük homebrewn yöntemini MPI işlemlerine hata ayıklayıcı eklemek için kullanıyorum - kodunuzda MPI_Init () 'den hemen sonra DebugWait () işlevini çağırın. Artık işlemler klavye girdisini beklerken, hata ayıklayıcıyı bunlara eklemek ve kesme noktaları eklemek için her zamanınız var. İşiniz bittiğinde, tek bir karakter girişi sağlayın ve gitmeye hazırsınız.

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);
}

Elbette bu işlevi yalnızca hata ayıklama yapıları için derlemek istersiniz.


MPI, basit bir kod için bile şimdiye kadar yazdığım en hata ayıklama ifadelerini gerektirdi. (lol) Bu çok yardımcı olabilir.
Troggy

3
Bu çözüm, buradaki madde 6'ya benzer ( open-mpi.org/faq/?category=debugging#serial-debuggers ). Kodunuzu ekleyerek biraz geliştirebilirsiniz gethostname(hostname, sizeof(hostname)); printf("PID %d on host %s ready for attach\n", getpid(), hostname);. Ardından, işleme yazarak rsh <hostname_from_print_statement>ve son olarak da iliştirirsiniz gdb --pid=<PID_from_print_statement>.
Jeff

2

Gdb'yi bir mpi işlemine ekleme komutu eksik,

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

Mpi ve gdb hakkında kısa bir tartışma burada bulunabilir


2

Bir MPI programında hata ayıklamanın oldukça basit bir yolu.

Main () işlevinde uyku ekle (bir_saniye)

Programı her zamanki gibi çalıştırın

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

Program başlayacak ve uykuya geçecektir.

Böylece süreçlerinizi ps ile bulmak, gdb'yi çalıştırmak ve bunlara eklemek için birkaç saniyeniz olacak.

QtCreator gibi bir düzenleyici kullanıyorsanız,

Hata ayıklama-> Hata ayıklamaya başla-> Çalışan uygulamaya ekle

ve orada süreçleri bul.


1

Günlük izleme ile bazı MPI ile ilgili hata ayıklama yapıyorum, ancak mpich2: MPICH2 ve gdb kullanıyorsanız gdb'yi de çalıştırabilirsiniz . Bu teknik, genel olarak bir hata ayıklayıcıdan başlatılması zor olan bir işlemle uğraşırken iyi bir uygulamadır.


Bozuk olmayan başka bir bağlantıyla değiştirildi, bazı yorumlar eklendi.
Jim Hunziker


0

Diğer bir çözüm, kodunuzu simüle edilmiş MPI olan SMPI içinde çalıştırmaktır. Bu, dahil olduğum açık kaynaklı bir proje. Her MPI derecesi, aynı UNIX sürecinin iş parçacığına dönüştürülecektir. Daha sonra MPI derecelerini yükseltmek için gdb'yi kolayca kullanabilirsiniz.

SMPI, MPI uygulamalarının çalışılmasına başka avantajlar da sunar: durugörü (sistemin her parçasını gözlemleyebilirsiniz), tekrarlanabilirlik (belirtmediğiniz sürece birkaç çalıştırma tam olarak aynı davranışa yol açar), heisenbug'ların yokluğu (simüle edilen platform farklı tutulduğundan ana bilgisayardan) vb.

Daha fazla bilgi için bu sunuma veya ilgili cevaba bakın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.