मैं MPI प्रोग्राम को कैसे डिबग करूं?


129

मेरे पास एक एमपीआई कार्यक्रम है जो संकलन करता है और चलाता है, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि कुछ भी विचित्र नहीं हो रहा है। आदर्श रूप से, मैं GDB को किसी विशेष प्रक्रिया में संलग्न करने का एक सरल तरीका चाहूंगा, लेकिन मुझे वास्तव में यकीन नहीं है कि यह संभव है या यह कैसे करना है। एक विकल्प एक अलग लॉग फ़ाइल के लिए डिबग आउटपुट लिखने वाली प्रत्येक प्रक्रिया होगी, लेकिन यह वास्तव में डीबगर के रूप में समान स्वतंत्रता नहीं देता है।

क्या बेहतर दृष्टिकोण हैं? आप MPI प्रोग्राम को कैसे डिबग करते हैं?

जवाबों:


62

जैसा कि किसी और ने कहा, TotalView इसके लिए मानक है। लेकिन यह आपको एक हाथ और एक पैर की कीमत देगा।

OpenMPI साइट में MPI डीबगिंग पर एक बहुत अच्छा FAQ है । FAQ में आइटम # 6 बताता है कि GDB को MPI प्रक्रियाओं से कैसे जोड़ा जाए। पूरी बात पढ़ें, कुछ बेहतरीन टिप्स हैं।

यदि आप पाते हैं कि आपके पास अभी तक बहुत सारी प्रक्रियाएँ हैं, तो इस पर नज़र रखने के लिए, स्टैक ट्रेस एनालिसिस टूल (STAT) देखें । हम लिवरमोर में इसका उपयोग संभावित रूप से चलने वाली सैकड़ों हजारों प्रक्रियाओं से स्टैक के निशान को इकट्ठा करने और उन्हें उपयोगकर्ताओं को समझदारी से पेश करने के लिए करते हैं। यह पूर्ण विशेषताओं वाला डिबगर नहीं है (एक पूर्ण विशेषताओं वाला डिबगर कभी भी 208k कोर के पैमाने पर नहीं होगा), लेकिन यह आपको बताएगा कि प्रक्रियाओं के कौन से समूह एक ही काम कर रहे हैं। फिर आप मानक डीबगर में प्रत्येक समूह के प्रतिनिधि के माध्यम से कदम रख सकते हैं।


14
2010 के रूप में एलिनिया डीडीटी एक पूर्ण विशेषताओं वाला डिबगर है जो 208k कोर से अधिक के पैमाने पर है
मार्क

1
इसलिए मैं यहाँ पर @ मार्क के उत्तर को आगे बढ़ाऊंगा। डीडीटी अच्छी है। इसे भी आजमाएं। TotalView भी अब STAT के साथ एकीकृत हो जाता है, इसलिए यदि आपकी साइट में TotalView इंस्टॉलेशन है तो आप इसे भी आजमा सकते हैं। LLNL TotalView और DDT को अपने आसपास रखता है, और यह अच्छा है कि TotalView में आखिरकार कुछ कड़ी प्रतिस्पर्धा है।
टॉड गैम्बलिन

मैं MPI डीबगिंग ( FAQ-mpi.org/faq/?category=debugging#serial-debuggers ) पर पूछे जाने वाले प्रश्न के लिए दूसरी कड़ी चाहूंगा । विशेष रूप से, बुलेट 6 एक अच्छी, त्वरित और आसान (मेरे लिए भी पर्याप्त है!) कम से कम एक व्यक्तिगत प्रक्रिया को समझने का तरीका समझने के लिए।
जेफ

FAQ पृष्ठ के # 6 में दिए गए कदमों ने मेरे लिए बहुत अच्छा काम किया और मुझे अपनी समस्या का पता लगाने में मदद की। इस लिए आपका बहुत - बहुत धन्यवाद।
जॉन डेटन

86

मैंने gdb को काफी उपयोगी पाया है। मैं इसका उपयोग करता हूं

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

यह xterm विंडो लॉन्च करता है जिसमें मैं कर सकता हूं

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

आमतौर पर ठीक काम करता है

आप इन आदेशों को एक साथ प्रयोग करके पैकेज कर सकते हैं:

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

मैं सभी एनपी जीडीबी xterms में एक ही इनपुट कैसे भेज सकता हूं? उदाहरण के लिए, मैं हर प्रक्रिया में दो ब्रेकप्वाइंट जोड़ना चाहता हूं, और 16 प्रक्रियाएं हैं। क्या ऐसा करने के लिए xterm का कोई विकल्प है? क्या हम सत्र को स्क्रीन, tmux या क्रिस जोन्स के टर्मिनेटर के एकल उदाहरण में जोड़ सकते हैं?
असग

@osgx आप के लिए आदेश ( "तोड़ xxx", "तोड़ yyy", "रन") की बचत करके ऐसा कर सकते <file>हैं और गुजर -x <file>GDB करने के लिए।
eush77

लेकिन मैं एक त्रुटि को पूरा करता हूं, त्रुटि संदेश "फ़ाइल xterm पर कोई त्रुटि
निष्पादित करें

जब मैं jdb और OpenMPI के साथ यह कोशिश करता हूं, तो यह काम नहीं करता है, अर्थात प्रत्येक jdb उदाहरण 1 के num_ranks को देखता है, बजाय -np तर्क के। किसी भी विचार क्यों?
मिशेल मुलर

26

यहां कई पोस्ट GDB के बारे में हैं, लेकिन उल्लेख नहीं है कि स्टार्टअप से प्रक्रिया कैसे संलग्न करें। जाहिर है, आप सभी प्रक्रियाओं से जुड़ सकते हैं:

mpiexec -n X gdb ./a.out

लेकिन वह बेतहाशा अप्रभावी है क्योंकि आपको अपनी सभी प्रक्रियाओं को शुरू करने के लिए चारों ओर उछालना होगा। यदि आप केवल MPI प्रक्रिया में से किसी एक (या कम संख्या में) को डीबग करना चाहते हैं, तो आप :ऑपरेटर का उपयोग करके कमांड लाइन पर एक अलग निष्पादन योग्य के रूप में जोड़ सकते हैं :

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

अब आपकी केवल एक प्रक्रिया को GDB मिलेगा।


मैं "mpiexec -n X gdb ./a.out" का उपयोग कर सकता हूं, लेकिन क्या gdb -tui मोड का उपयोग करने का कोई तरीका है?
हिटवैल

16

जैसा कि दूसरों ने उल्लेख किया है, यदि आप केवल मुट्ठी भर MPI प्रक्रियाओं के साथ काम कर रहे हैं, तो आप कई gdb सत्रों का उपयोग करने की कोशिश कर सकते हैं , redoubtable valgrind या अपने स्वयं के प्रिंट / लॉगिंग समाधान को रोल कर सकते हैं।

यदि आप उससे अधिक प्रक्रियाओं का उपयोग कर रहे हैं, तो आपको वास्तव में एक उचित डिबगर की आवश्यकता है। Openmpi पूछे जाने वाले प्रश्न दोनों की सिफारिश की Allinea डीडीटी और TotalView

मैं एलिनिया डीडीटी पर काम करता हूं । यह एक पूर्ण विशेषताओं वाला, चित्रमय स्रोत-कोड डीबगर है तो हाँ, आप कर सकते हैं:

  • डीबग या (200k से अधिक) MPI प्रक्रियाओं के साथ संलग्न करें
  • उन्हें समूहों में या व्यक्तिगत रूप से कदम और रोकें
  • ब्रेकपॉइंट, घड़ियां और ट्रेसप्वाइंट जोड़ें
  • मेमोरी त्रुटियों और लीक को पकड़ो

...और इसी तरह। यदि आपने ग्रहण या विजुअल स्टूडियो का उपयोग किया है तो आप घर पर सही रहेंगे।

हमने विशेष रूप से समानांतर कोड डिबगिंग के लिए कुछ दिलचस्प विशेषताएं जोड़ी हैं (यह MPI, बहु-थ्रेडेड या CUDA हो)

  • स्केलर चर सभी प्रक्रियाओं की तुलना में स्वचालित रूप से होते हैं: (स्रोत: allinea.com )प्रक्रियाओं में मूल्य दिखाने वाली स्पार्कलाइन

  • आप प्रक्रियाओं और समय पर चर और भावों के मूल्यों का पता लगा सकते हैं और फ़िल्टर कर सकते हैं: ट्रेसपॉइंट समय के साथ मानों को लॉग करते हैं

यह ORNL , NCSA , LLNL , Jülich et जैसे टॉप 500 HPC साइट्स के बीच व्यापक रूप से उपयोग किया जाता है । अल।

इंटरफ़ेस बहुत तेज़ है; हम ओक रिज के जगुआर क्लस्टर पर स्वीकृति परीक्षण के भाग के रूप में 0.1 के स्तर पर 220,000 प्रक्रियाओं के स्टैक और वैरिएबल को चरणबद्ध और विलय कर रहे हैं।

@tgamblin उत्कृष्ट उल्लेख STAT , जो से जुड़ता है Allinea डीडीटी , के रूप में कई अन्य लोकप्रिय ओपन सोर्स प्रोजेक्ट है।


8

4
Valgrind एक इंटरैक्टिव डिबगर के समान नहीं है, लेकिन यह जानकर अच्छा लगता है कि यह MPI के साथ काम करता है।
जे कॉनरोड

7

यदि आप एक tmuxउपयोगकर्ता हैं तो आप बेनेडिक्ट मोरबैक की स्क्रिप्ट का उपयोग करके बहुत सहज महसूस करेंगे :tmpi

मूल स्रोत: https://github.com/moben/scripts/blob/master/tmpi

कांटा: https://github.com/Azrael3000/tmpi

इसके साथ आपके पास कई पैनल हैं (प्रक्रियाओं की संख्या) सभी सिंक्रनाइज़ (प्रत्येक कमांड को एक ही समय में सभी पैनलों या प्रक्रियाओं पर कॉपी किया जाता है ताकि आप xterm -eदृष्टिकोण की तुलना करने में बहुत समय बचा सकें )। इसके अलावा आप उस प्रक्रिया में चर के मूल्यों को जान सकते हैं जो आप printबिना किसी अन्य पैनल में जाने के लिए कर रहे हैं, यह प्रत्येक पैनल पर प्रत्येक प्रक्रिया के लिए चर के मूल्यों को प्रिंट करेगा।

यदि आप एक tmuxउपयोगकर्ता नहीं हैं, तो मैं इसे आज़माने और देखने के लिए दृढ़ता से सलाह देता हूं।


2
चूँकि tmpi वास्तव में शानदार है और वास्तव में मैं जो देख रहा था, मैंने इसे अपने github खाते पर कांटा: github.com/Azrael3000/tmpi क्योंकि मूल लेखक ने इसे हटा दिया था
Azrael3000

6

http://github.com/jimktrains/pgdb/tree/master एक उपयोगिता है जिसे मैंने यह करने के लिए लिखा था। कुछ डॉक्स हैं और सवालों के जवाब देने के लिए बेझिझक मुझे बताएं।

आप मूल रूप से एक पर्ल प्रोग्राम कहते हैं जो GDB और फ़नल को लपेटता है जो एक केंद्रीय सर्वर के लिए IO है। यह GDB को प्रत्येक होस्ट पर और टर्मिनल पर प्रत्येक होस्ट पर इसे एक्सेस करने की अनुमति देता है।


धन्यवाद! अगली बार जब मैं MPI में काम कर रहा हूँ तो मैं निश्चित रूप से इसकी जाँच करूँगा।
जे कॉनरोड

5

MPI अनुप्रयोगों को डिबग करने के लिए screenएक साथ उपयोग करना gdbअच्छी तरह से काम करता है, खासकर यदि xtermअनुपलब्ध है या आप कुछ प्रोसेसर से अधिक के साथ काम कर रहे हैं। स्टैकओवरफ्लो खोजों के साथ रास्ते में कई नुकसान थे, इसलिए मैं अपने समाधान को पूरा करूँगा।

सबसे पहले, पीआईडी ​​प्रिंट करने के लिए MPI_Init के बाद कोड जोड़ें और प्रोग्राम को अटैच करने के लिए रुकें। मानक समाधान एक अनंत लूप लगता है; मैं अंततः बस गया raise(SIGSTOP);, जिसे continuegdb के भीतर भागने के लिए अतिरिक्त कॉल की आवश्यकता थी ।

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

संकलित करने के बाद, पृष्ठभूमि में निष्पादन योग्य चलाएं, और स्टेडर को पकड़ें। फिर आप grepप्रत्येक प्रक्रिया के PID और रैंक प्राप्त करने के लिए कुछ कीवर्ड (यहां शाब्दिक PID) के लिए stderr फाइल कर सकते हैं ।

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बैश करने का विकल्प इसे इंटरैक्टिव मोड में शुरू करता है और जीडीबी को तुरंत बाहर निकलने से रोकता है।

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

एक बार जब स्क्रीन में जीडीबी शुरू हो जाता है, तो आप स्क्रीन पर स्क्रिप्ट इनपुट कर सकते हैं (ताकि आपको हर स्क्रीन में प्रवेश न करना पड़े और उसी चीज को टाइप करें) स्क्रीन की -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 सत्रों में कमांड भेजे जा सकते हैं।


3

मेरा ओपन-सोर्स टूल, पैडब भी है, जिसका लक्ष्य समानांतर प्रोग्रामिंग में मदद करना है। मैं इसे "जॉब इंस्पेक्शन टूल" कहता हूं क्योंकि यह न केवल एक डिबगर के रूप में कार्य करता है, बल्कि उदाहरण के लिए एक समानांतर टॉप प्रोग्राम की तरह भी कार्य कर सकता है। "पूर्ण रिपोर्ट" मोड में चलाएं यह आपको अपने आवेदन के भीतर हर प्रक्रिया के स्टैक के निशान दिखाएगा और साथ ही प्रत्येक रैंक के लिए प्रत्येक फ़ंक्शन के लिए स्थानीय चर के साथ (आप -g के साथ संकलित मान लेंगे)। यह आपको "एमपीआई संदेश कतारें" भी दिखाएगा, जो कि नौकरी के भीतर प्रत्येक रैंक के लिए बकाया भेजता है और प्राप्त करता है।

पूरी रिपोर्ट दिखाने के साथ ही पैडब को नौकरी के भीतर अलग-अलग सूचनाओं पर ज़ूम करने के लिए भी बताना संभव है, जो जानकारी दिखाई जाती है, उसे नियंत्रित करने के लिए विकल्पों और कॉन्फ़िगरेशन आइटमों का असंख्य विवरण है, अधिक विवरण के लिए वेब पेज देखें।

Padb


3

एमपीआई कार्यक्रमों को डिबग करने का "मानक" तरीका एक डिबगर का उपयोग करके है जो उस निष्पादन मॉडल का समर्थन करता है।

UNIX पर, TotalView को MPI के लिए अच्छा सपोर्ट माना जाता है।


2

मैं MPI प्रक्रियाओं के डीबगर को संलग्न करने के लिए इस छोटे होमब्रेव विधि का उपयोग करता हूं - अपने कोड में MPI_Init () के ठीक बाद, निम्न फ़ंक्शन, डिबगवाट () को कॉल करें। अब जबकि प्रक्रियाएँ कीबोर्ड इनपुट की प्रतीक्षा कर रही हैं, आपके पास डिबगर को उनके साथ जोड़ने और ब्रेकप्वाइंट जोड़ने के लिए हर समय है। जब आप कर लें, तो एक एकल वर्ण इनपुट प्रदान करें और आप जाने के लिए तैयार हैं।

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

बेशक आप डिबग बिल्ड के लिए इस फ़ंक्शन को संकलित करना चाहते हैं।


MPI को सबसे अधिक डिबग स्टेटमेंट की आवश्यकता है जो मैंने कभी भी सरल कोड के लिए लिखा है। (lol) यह बहुत मददगार हो सकता है।
ट्रोगी जूल

3
यह समाधान यहां बुलेट 6 के समान है ( open-mpi.org/faq/?category=debugging#serial-debuggers )। आप जोड़कर अपने कोड को थोड़ा सुधार सकते हैं gethostname(hostname, sizeof(hostname)); printf("PID %d on host %s ready for attach\n", getpid(), hostname);। उसके बाद, आप टाइप करके प्रक्रिया को देते हैं rsh <hostname_from_print_statement>, और अंत में gdb --pid=<PID_from_print_statement>
जेफ

2

Gdb को एक mpi प्रक्रिया में संलग्न करने की कमांड अधूरी है, यह होनी चाहिए

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

Mpi और gdb की संक्षिप्त चर्चा यहाँ मिल सकती है


2

एक MPI कार्यक्रम डिबग करने के लिए एक सरल तरीका काफी है।

मुख्य () फ़ंक्शन में नींद जोड़ें (some_seconds)

कार्यक्रम को हमेशा की तरह चलाएं

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

कार्यक्रम शुरू होगा और नींद में हो जाएगा।

तो आपके पास पीएस द्वारा प्रक्रियाएं खोजने के लिए कुछ सेकंड होंगे, जीडीबी चलाएं और उन्हें संलग्न करें।

यदि आप QtCreator जैसे कुछ संपादक का उपयोग करते हैं, तो आप उपयोग कर सकते हैं

डिबग-> डिबगिंग शुरू करें-> रनिंग एप्लिकेशन से अटैच करें

और तुम वहाँ प्रक्रियाओं पाते हैं।


1

मैं लॉग ट्रैस के साथ कुछ MPI से संबंधित डिबगिंग करता हूं, लेकिन यदि आप mpich2: MPICH2 और gdb का उपयोग कर रहे हैं तो आप gdb भी चला सकते हैं । यह तकनीक सामान्य रूप से एक अच्छा अभ्यास है जब आप एक ऐसी प्रक्रिया से निपट रहे हैं जो डिबगर से लॉन्च करने के लिए मुश्किल है।


एक और कड़ी में बदल गया है जो टूटी नहीं है, कुछ टिप्पणी जोड़ी गई
जिम हंज़िकर


0

एक और उपाय है, अपने कोड को SMPI, सिम्युलेटेड MPI के भीतर चलाना। यह एक ओपन सोर्स प्रोजेक्ट है जिसमें मैं शामिल हूं। प्रत्येक MPI रैंक को समान UNIX प्रक्रिया के थ्रेड में परिवर्तित किया जाएगा। फिर आप MPI रैंक को बढ़ाने के लिए आसानी से gdb का उपयोग कर सकते हैं।

एमपीएमआई अनुप्रयोगों के अध्ययन के लिए एसएमपीआई अन्य लाभों का प्रस्ताव करता है: क्लेयरवॉयेंस (आप सिस्टम के हर हिस्से का निरीक्षण कर सकते हैं), आर्युपिसबिलिटी (कई रन ठीक उसी व्यवहार को जन्म देते हैं जब तक कि आप ऐसा निर्दिष्ट नहीं करते हैं), हाइजेनबग्स की अनुपस्थिति (जैसा कि नकली प्लेटफॉर्म को अलग रखा गया है) मेजबान से), आदि।

अधिक जानकारी के लिए, इस प्रस्तुति , या उस संबंधित उत्तर को देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.