ฉันจะดีบักโปรแกรม MPI ได้อย่างไร


129

ฉันมีโปรแกรม MPI ที่รวบรวมและใช้งานได้ แต่ฉันต้องการที่จะผ่านมันเพื่อให้แน่ใจว่าไม่มีอะไรแปลกประหลาดเกิดขึ้น เป็นการดีที่ฉันต้องการวิธีง่ายๆในการแนบ GDB กับกระบวนการเฉพาะ แต่ฉันไม่แน่ใจจริงๆว่าเป็นไปได้หรือจะทำอย่างไร อีกทางเลือกหนึ่งคือให้แต่ละกระบวนการเขียนเอาต์พุตดีบักไปยังล็อกไฟล์แยกกัน แต่นี่ไม่ได้ให้อิสระเหมือนกับตัวดีบัก

มีแนวทางที่ดีกว่านี้ไหม? คุณจะดีบักโปรแกรม MPI ได้อย่างไร

คำตอบ:


62

ตามที่คนอื่นพูดว่าTotalViewเป็นมาตรฐานสำหรับสิ่งนี้ แต่มันจะทำให้คุณเสียแขนและขา

เว็บไซต์ OpenMPI มีดีคำถามที่พบบ่อยเกี่ยวกับการแก้จุดบกพร่อง MPI รายการ # 6 ในคำถามที่พบบ่อยอธิบายวิธีแนบ GDB กับกระบวนการ MPI อ่านเรื่องทั้งหมดมีเคล็ดลับดีๆ

หากคุณพบว่าคุณมีกระบวนการไกลมากเกินไปที่จะติดตาม แต่ตรวจสอบกองเครื่องมือการวิเคราะห์ติดตาม (สถิติ) เราใช้สิ่งนี้ที่ Livermore เพื่อรวบรวมร่องรอยสแต็คจากกระบวนการที่กำลังทำงานอยู่หลายแสนครั้งและเพื่อเป็นตัวแทนผู้ใช้อย่างชาญฉลาด มันไม่ใช่ debugger ที่มีคุณสมบัติครบถ้วน (debugger ที่มีคุณสมบัติครบถ้วนจะไม่ขยายไปถึง 208k cores) แต่มันจะบอกคุณว่ากลุ่มของกระบวนการใดกำลังทำสิ่งเดียวกัน จากนั้นคุณสามารถผ่านตัวแทนจากแต่ละกลุ่มในดีบักเกอร์มาตรฐาน


14
ในปี 2010 Allinea DDTเป็นตัวดีบักเต็มรูปแบบที่ปรับขยายได้มากกว่า 208k คอร์
Mark

1
ดังนั้นฉันจะไปข้างหน้าและโหวตคำตอบ @ Mark ที่นี่ ดีดีทีดี ลองด้วย TotalView ยังทำงานร่วมกับ STAT ทันทีดังนั้นหากเว็บไซต์ของคุณมีการติดตั้ง TotalView คุณสามารถลองใช้งานได้เช่นกัน LLNL คอยดูแล TotalView และ DDT และเป็นเรื่องดีที่ TotalView จะมีการแข่งขันที่ดุเดือด
ทอดด์ Gamblin

ฉันต้องการลิงก์ไปยังคำถามที่พบบ่อยเกี่ยวกับการดีบัก MPI ( open-mpi.org/faq/?category=debugging#serial-debuggers ) โดยเฉพาะอย่างยิ่ง bullet 6 เป็นวิธีที่ดีรวดเร็วและง่าย (พอสำหรับฉัน!) เพื่อให้เข้าใจวิธีที่จะทำการดีบักแต่ละกระบวนการอย่างน้อยที่สุด
Jeff

ขั้นตอนใน # 6 ของหน้าคำถามที่พบบ่อยใช้งานได้ดีสำหรับฉันและช่วยให้ฉันเข้าใจปัญหาได้ ขอบคุณมากสำหรับสิ่งนี้
Jon Deaton

86

ฉันพบว่า gdb มีประโยชน์มาก ฉันใช้มันเป็น

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

นี่เป็นการเปิดตัว xterm windows ที่ฉันสามารถทำได้

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

มักจะทำงานได้ดี

คุณยังสามารถทำแพ็คเกจคำสั่งเหล่านี้พร้อมกันโดยใช้:

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

ฉันจะส่งอินพุตเดียวกันไปยัง NP gdb xterms ทั้งหมดได้อย่างไร ตัวอย่างเช่นฉันต้องการเพิ่มจุดพักสองจุดในทุกกระบวนการและมี 16 กระบวนการ มีทางเลือกอื่นในการ xterm ในการทำเช่นนี้หรือไม่? เราสามารถเชื่อมต่อเซสชันในอินสแตนซ์เดียวของหน้าจอ tmux หรือ Terminator ของ Chris Jones ได้หรือไม่?
osgx

@osgx คุณสามารถทำได้โดยการบันทึกคำสั่ง ("break xxx", "break yyy", "run") ไปยัง<file>และผ่าน-x <file>ไปยัง gdb
eush77

แต่ฉันพบข้อผิดพลาดข้อผิดพลาดคือ "ข้อผิดพลาด execvp ในไฟล์ xterm (ไม่มีไฟล์หรือไดเรกทอรีดังกล่าว)"
hitwlh

เมื่อฉันลองสิ่งนี้ด้วย jdb & OpenMPI มันไม่ทำงานเช่น jdb แต่ละอินสแตนซ์เห็น num_ranks เป็น 1 แทนสิ่งที่กำหนดให้กับอาร์กิวเมนต์ -np คิดอะไรทำไม
Michel Müller

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 ไหม?
hitwlh

16

ดังที่คนอื่น ๆ พูดถึงถ้าคุณทำงานกับโพรเซส MPI เพียงหยิบมือเดียวคุณสามารถลองใช้หลาย ๆ gdb เซสชัน , valgrind ที่น่าสงสัยหรือม้วนโซลูชัน printf / การบันทึกของคุณเอง

หากคุณกำลังใช้กระบวนการมากกว่านั้นคุณต้องเริ่มต้นโปรแกรมดีบั๊กที่เหมาะสม OpenMPI คำถามที่พบบ่อยแนะนำทั้งAllinea ดีดีทีและTotalView

การทำงานของผมในAllinea ดีดีที มันเป็นดีบักเกอร์ซอร์สโค้ดกราฟิกที่มีคุณสมบัติครบถ้วนดังนั้นใช่คุณสามารถ:

  • ตรวจแก้จุดบกพร่องหรือแนบไปกับกระบวนการ MPI (มากกว่า 200k)
  • ขั้นตอนและหยุดพวกเขาเป็นกลุ่มหรือเป็นรายบุคคล
  • เพิ่มจุดพัก, นาฬิกาข้อมือและจุดติดตาม
  • ตรวจจับข้อผิดพลาดและการรั่วไหลของหน่วยความจำ

... และต่อไป หากคุณใช้ Eclipse หรือ Visual Studio คุณจะอยู่ที่บ้าน

เราได้เพิ่มคุณสมบัติที่น่าสนใจบางอย่างโดยเฉพาะสำหรับการดีบักโค้ดแบบขนาน (ไม่ว่าจะเป็น MPI, แบบมัลติเธรดหรือ CUDA):

  • ตัวแปรสเกลาร์จะถูกเปรียบเทียบโดยอัตโนมัติในทุกกระบวนการ: (ที่มา: allinea.com )ประกายไฟแสดงค่าระหว่างกระบวนการ

  • คุณยังสามารถติดตามและกรองค่าของตัวแปรและนิพจน์ในกระบวนการและเวลา: Tracepoints บันทึกค่าตลอดเวลา

มันถูกใช้อย่างกว้างขวางในหมู่500เว็บไซต์ HPC เช่นORNL , NCSA , LLNL , Jülichและ อัล

อินเตอร์เฟสค่อนข้างเร็ว เราหมดเวลาไปกับการรวมสแต็คและตัวแปรของกระบวนการ 220,000 กระบวนการที่ 0.1s ซึ่งเป็นส่วนหนึ่งของการทดสอบการยอมรับในคลัสเตอร์จากัวร์ของ Oak Ridge

@tgamblin พูดถึงSTAT ที่ยอดเยี่ยมซึ่งทำงานร่วมกับAllinea DDTได้เช่นเดียวกับโครงการโอเพ่นซอร์สยอดนิยมอื่น ๆ



7

หากคุณเป็นtmuxผู้ใช้คุณจะรู้สึกสบายใจเมื่อใช้สคริปต์ของBenedikt Morbach :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เป็นเครื่องมือที่ฉันเขียนมาเพื่อทำสิ่งนี้ มีเอกสารและรู้สึกฟรีเพื่อส่งคำถามให้ฉัน

โดยทั่วไปคุณเรียกโปรแกรม perl ที่ล้อม GDB และกรวยเป็น IO ไปยังเซิร์ฟเวอร์กลาง สิ่งนี้ช่วยให้ GDB สามารถทำงานบนแต่ละโฮสต์และให้คุณเข้าถึงในแต่ละโฮสต์ที่เทอร์มินัล


ขอบคุณ! ฉันจะตรวจสอบเรื่องนี้ในครั้งต่อไปที่ฉันทำงานใน MPI
เจ Conrod

5

การใช้งานscreenร่วมกับgdbเพื่อดีบักแอปพลิเคชั่น MPI ทำงานได้ดีโดยเฉพาะอย่างยิ่งหากxtermไม่สามารถใช้งานได้หรือคุณกำลังติดต่อกับโปรเซสเซอร์มากกว่าสองสามตัว มีข้อผิดพลาดมากมายระหว่างการค้นหา stackoverflow ที่มาพร้อมกันดังนั้นฉันจะทำซ้ำโซลูชันของฉันทั้งหมด

ขั้นแรกเพิ่มรหัสหลังจาก MPI_Init เพื่อพิมพ์ PID และหยุดโปรแกรมเพื่อรอให้คุณแนบ โซลูชันมาตรฐานดูเหมือนจะวนซ้ำไม่สิ้นสุด ในที่สุดฉันก็ตัดสินใจraise(SIGSTOP);ซึ่งจำเป็นต้องมีสายพิเศษcontinueเพื่อหลบหนีภายใน 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);
}

หลังจากรวบรวมแล้วให้เรียกใช้ไฟล์ปฏิบัติการในพื้นหลังและตรวจจับ stderr จากนั้นคุณสามารถgrepไฟล์ stderr สำหรับคำหลักบางคำ (นี่คือ PID ที่แท้จริง) เพื่อรับ PID และอันดับของแต่ละกระบวนการ

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ตัวเลือกในการทุบตีจะเริ่มในโหมดโต้ตอบและป้องกันไม่ให้ gdb ออกจากทันที

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

เมื่อ gdb เริ่มทำงานในหน้าจอคุณสามารถป้อนสคริปต์ไปยังหน้าจอ (เพื่อให้คุณไม่ต้องป้อนทุกหน้าจอและพิมพ์สิ่งเดียวกัน) โดยใช้-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

นอกจากนี้ยังมีเครื่องมือโอเพนซอร์สของฉัน padb ซึ่งมีจุดมุ่งหมายเพื่อช่วยในการเขียนโปรแกรมแบบขนาน ฉันเรียกมันว่า "เครื่องมือตรวจสอบงาน" เพราะฟังก์ชั่นไม่เพียง แต่ในขณะที่ดีบักเกอร์ยังสามารถทำงานตัวอย่างเช่นด้านบนขนานเช่นโปรแกรม เรียกใช้ในโหมด "รายงานฉบับเต็ม" มันจะแสดงให้คุณเห็นร่องรอยสแต็คของทุกกระบวนการในแอปพลิเคชันของคุณพร้อมกับตัวแปรท้องถิ่นสำหรับทุกฟังก์ชั่นเหนือทุกระดับ (สมมติว่าคุณรวบรวมด้วย -g) นอกจากนี้ยังจะแสดง "คิวข้อความ MPI" ซึ่งเป็นรายการของการส่งและรับที่โดดเด่นสำหรับแต่ละอันดับภายในงาน

เช่นเดียวกับการแสดงรายงานฉบับเต็มนอกจากนี้ยังเป็นไปได้ที่จะบอกให้ padb ซูมเข้าข้อมูลแต่ละบิตในงานนั้นมีตัวเลือกมากมายและรายการกำหนดค่าเพื่อควบคุมข้อมูลที่จะแสดงให้ดูหน้าเว็บสำหรับรายละเอียดเพิ่มเติม

Padb


3

วิธี "มาตรฐาน" ในการดีบักโปรแกรม MPI คือการใช้ดีบักเกอร์ซึ่งสนับสนุนรูปแบบการดำเนินการนั้น

บน UNIX TotalViewถูกกล่าวว่ามีส่วนสนับสนุนที่ดีสำหรับ MPI


2

ฉันใช้วิธี homebrewn นี้เพื่อแนบ debugger ไปยังกระบวนการ MPI - เรียกใช้ฟังก์ชันต่อไปนี้ DebugWait () ขวาหลังจาก 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 จำเป็นต้องมีคำสั่ง debug มากที่สุดที่ฉันเคยเขียนแม้แต่รหัสง่ายๆ (lol) สิ่งนี้มีประโยชน์มาก
Troggy

3
วิธีนี้คล้ายกับ bullet 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>
Jeff

2

คำสั่งสำหรับการแนบ gdb กับกระบวนการ mpi นั้นไม่สมบูรณ์ควรเป็น

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

สามารถสนทนาสั้น ๆ เกี่ยวกับ mpi และ gdb ได้ที่นี่


2

วิธีง่ายๆในการดีบักโปรแกรม MPI

ใน main () ฟังก์ชันเพิ่ม sleep (some_seconds)

เรียกใช้โปรแกรมตามปกติ

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

โปรแกรมจะเริ่มและเข้าสู่โหมดสลีป

ดังนั้นคุณจะมีเวลาไม่กี่วินาทีในการค้นหากระบวนการของคุณโดยใช้ ps, รัน gdb และแนบไปกับพวกเขา

หากคุณใช้โปรแกรมแก้ไขเช่น QtCreator คุณสามารถใช้

แก้ไขข้อบกพร่อง -> เริ่มแก้จุดบกพร่อง -> แนบกับแอปพลิเคชันที่กำลังรัน

และพบว่าคุณมีกระบวนการ


1

ฉันทำบางการแก้จุดบกพร่อง MPI ที่เกี่ยวข้องมีร่องรอยการเข้าสู่ระบบ แต่คุณยังสามารถเรียกใช้ gdb หากคุณกำลังใช้ mpich2: MPICH2 และ gdb เทคนิคนี้เป็นวิธีปฏิบัติที่ดีโดยทั่วไปเมื่อคุณต้องรับมือกับกระบวนการที่ยุ่งยากในการเริ่มจากตัวดีบั๊ก


เปลี่ยนเป็นลิงค์อื่นที่ไม่เสียเพิ่มความเห็น
Jim Hunziker


0

อีกวิธีคือการเรียกใช้รหัสของคุณภายใน SMPI, MPI จำลอง นั่นเป็นโครงการโอเพ่นซอร์สที่ฉันเกี่ยวข้อง ทุกระดับ MPI จะถูกแปลงเป็นเธรดของกระบวนการ UNIX เดียวกัน จากนั้นคุณสามารถใช้ gdb เพื่อจัดอันดับ MPI ได้อย่างง่ายดาย

SMPI เสนอข้อดีอื่น ๆ ให้กับการศึกษาแอพพลิเคชั่น MPI: clairevoyance (คุณสามารถสังเกตได้ทุกส่วนของระบบ), การทำซ้ำ (การทำงานหลายอย่างจะนำไปสู่พฤติกรรมเดียวกันที่แน่นอนเว้นแต่คุณจะระบุไว้), การขาด Heisenbugs จากโฮสต์หนึ่ง) ฯลฯ

สำหรับข้อมูลเพิ่มเติมโปรดดูที่นำเสนอนี้หรือว่าคำตอบที่เกี่ยวข้อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.