- 論壇徽章:
- 0
|
并行調(diào)試器 PDB(Parallel debugger) 簡(jiǎn)介 長(zhǎng)期以來,高性能并行環(huán)境下的程序調(diào)試一直是一個(gè)熱門話題。PDB 是 IBM 發(fā)布的一種強(qiáng)大的并行環(huán)境下的命令行調(diào)試工具。它能夠在并行程序運(yùn)行時(shí)觀察程序的所有 tasks 的內(nèi)部結(jié)構(gòu)和內(nèi)存的使用情況,方便用戶對(duì)并行程序進(jìn)行調(diào)試。與串行調(diào)試器相比,PDB V5.3 增加了以下功能(本文中均以 PDB V5.3 為例,進(jìn)行介紹): - 支持單步調(diào)試并行程序的每一個(gè) task
- 支持同時(shí)對(duì)并行程序的多個(gè) task 進(jìn)行調(diào)試
- 提供了一個(gè)控制中心,用來對(duì)并行程序的所有 tasks 進(jìn)行集中管理
- 支持同時(shí)對(duì)多達(dá) 1024k 的任務(wù)進(jìn)行調(diào)試
- 提供了一種機(jī)制,可以讓用戶自定義消息過濾準(zhǔn)則。
- 支持對(duì)數(shù)據(jù)進(jìn)行分類顯示
PDB 的架構(gòu)(如圖 1)的核心部分,是具有多層的樹形結(jié)構(gòu)的 SCI(Scalable Communication Infrastructure)—它可以啟動(dòng)及管理并行程序的所有分布式的 tasks,所有的通信及任務(wù)管理都由 SCI 完成。PDB 底層調(diào)用的是串行調(diào)試器 GDB,即 GNU Project Debugger(在 Linux 系統(tǒng)上),及 DBX(在 AIX 系統(tǒng)上)。使用 PDB 進(jìn)行調(diào)試,類似于同時(shí)啟動(dòng)多個(gè) GDB(DBX),對(duì)并行程序的多個(gè)任務(wù)同時(shí)進(jìn)行調(diào)試。關(guān)于 PDB 的基本信息請(qǐng)參見“參考資源”中的 IBM Publication: 《 Parallel Environment for AIX and Linux V5.2.1 》的“Using the PDB debugger”章節(jié)。
圖 1. PDB 的架構(gòu)
PDB 的兩種啟動(dòng)方式:Launch 模式和 Attach 模式 編譯并行程序 使用 PDB 進(jìn)行調(diào)試,必須使并行程序在編譯時(shí)包含調(diào)試信息,即在編譯時(shí)用“-g”選項(xiàng)打開調(diào)試選項(xiàng)。調(diào)試信息包含程序里的每個(gè)變量的類型和在可執(zhí)行文件里的地址映射以及源代碼的行號(hào)。PDB 利用這些信息使源代碼和機(jī)器碼相關(guān)聯(lián)。 下面是本文中要用 PDB 調(diào)試的并行程序。此程序調(diào)用 MPI(Message Passing Interface,消息傳遞接口)函數(shù)初始化并行環(huán)境,查詢應(yīng)用中進(jìn)程的總數(shù)等,進(jìn)行點(diǎn)對(duì)點(diǎn)通信,傳輸消息,以及結(jié)束該并行環(huán)境。
清單 1. 并行程序“mpihello.c”文件的代碼:
#include "mpi.h" void main(int argc, char **argv) { int numprocs,myrank,i,namelen; MPI_Status status; char msg[128]; char processor_name[MPI_MAX_PROCESSOR_NAME]; /* 調(diào)用 MPI_Init 函數(shù),初始化并行環(huán)境 */ MPI_Init(&argc,&argv); /* 調(diào)用 MPI_Comm_size 函數(shù),查詢進(jìn)程總數(shù) */ MPI_Comm_size(MPI_COMM_WORLD,&numprocs); /* 調(diào)用 MPI_Comm_rank 函數(shù),查詢當(dāng)前進(jìn)程的標(biāo)識(shí)號(hào) */ MPI_Comm_rank(MPI_COMM_WORLD,&myrank); /* 調(diào)用 MPI_Get_processor_name 函數(shù),查詢當(dāng)前進(jìn)程運(yùn)行的機(jī)器的名稱 */ MPI_Get_processor_name(processor_name,&namelen); /* 每一個(gè)進(jìn)程都向進(jìn)程 0 發(fā)送消息 */ strcpy(msg,"hello world!" ; sprintf(msg,"hello world from %s",processor_name); MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,0,99,MPI_COMM_WORLD); /* 進(jìn)程 0 從所有進(jìn)程接收消息,并將其打印 */ if(myrank ==0) { for (i=0;i<numprocs;i++) { MPI_Recv(msg,strlen(msg)+1,MPI_CHAR,i,99,MPI_COMM_WORLD,&status); printf("Message from %d of %d: %s\n",i,numprocs,msg); } } /* 調(diào)用 MPI_Finalize 函數(shù),結(jié)束并行環(huán)境 */ MPI_Finalize(); } |
利用 IBM 并行編譯器 mpcc 編譯該并行程序(在編譯時(shí)用“-g”選項(xiàng)打開調(diào)試選項(xiàng)): $ mpcc -g -o mpihello mpihello.c |
利用 IBM 并行環(huán)境運(yùn)行該并行程序的結(jié)果為(其中:參數(shù)“-procs 2”指定了該并行程序以兩個(gè)任務(wù)運(yùn)行): $ poe ./mpihello -procs 2 Message from 0 of 2: hello world from node1 Message from 1 of 2: hello world from node2 |
下面將介紹使用 PDB 的兩種啟動(dòng)方式對(duì)該并行程序進(jìn)行調(diào)試。 PDB 的兩種啟動(dòng)方式 根據(jù)一個(gè)調(diào)試會(huì)話是如何啟動(dòng)的,PDB 分為兩種啟動(dòng)方式:“Launch”模式和“Attach”模式。 “Launch”模式 : “Launch”模式,即使用 PDB 啟動(dòng)一個(gè)新的調(diào)試進(jìn)程。在 Launch mode 下,PDB 必須啟動(dòng)在該并行程序希望被執(zhí)行(即 poe 希望被執(zhí)行)的主機(jī)上。其啟動(dòng)方式如下:
清單 2. “Launch”模式啟動(dòng)方式:
pdb executable_and_arguments [--poe poe_options] [--gdb gdb_options] (Linux only) or [--dbx dbx_options] (AIX only) FLAGS executable_and_arguments Specifies to launch the target executable and start debugging from the beginning of the program. The arguments are to the executable, not to PDB. --gdb gdb_options Specifies the options to pass to GDB. Applies to Linux only. --dbx dbx_options Specifies the options to pass to dbx. Applies to AIX only. --poe poe_options Specifies the options to pass to POE. |
例如以“Launch”模式啟動(dòng) PDB,調(diào)試一個(gè)并行程序“mpihello”,如下所示(其中:參數(shù)“-procs 2”指定了該并行程序以兩個(gè)任務(wù)運(yùn)行,參數(shù)“-hostfile”指定了將要執(zhí)行該并行程序的主機(jī)列表): $ pdb ./mpihello --poe -procs 2 -hostfile ./host.list |
“Attach”模式: “Attach”模式,即使用 PDB 掛接一個(gè)正在運(yùn)行的進(jìn)程。在“Attach”模式下,PDB 必須啟動(dòng)在該并行程序已經(jīng)被執(zhí)行(即 poe 已經(jīng)被啟動(dòng))的主機(jī)上。其啟動(dòng)方式如下:
清單 3. “Attach”模式啟動(dòng)方式:
pdb -a [poe_process_id] [--gdb gdb_options] (Linux only) or [--dbx dbx_options] (AIX only) FLAGS executable_and_arguments Specifies to launch the target executable and start debugging from the beginning of the program. The arguments are to the executable, not to PDB. -a [poe_process_id] Specifies to attach to a running POE job. pdb -a must be issued from the node on which the POE job was initiated. If the POE process ID is not specified, PDB tries to find one and reports an error if multiple POE processes exist. --gdb gdb_options Specifies the options to pass to GDB. Applies to Linux only. --dbx dbx_options Specifies the options to pass to dbx. Applies to AIX only. |
例如以“Attach”模式啟動(dòng) PDB,掛接一個(gè)已經(jīng)被執(zhí)行的并行程序“mpihello”(進(jìn)程號(hào)為 [poe_pid])進(jìn)行調(diào)試,如下所示:
PDB 啟動(dòng)以后,可以利用 DBX/GDB 命令,以及 PDB 內(nèi)部命令對(duì)并行程序進(jìn)行調(diào)試。 控制中心 PDB 成功啟動(dòng)后,提供了一個(gè)控制中心 console,用來對(duì)被啟動(dòng)的并行程序的所有 tasks 進(jìn)行集中管理。除了該控制中心外,PDB 還可以通過以下方式掛接新的控制中心到該調(diào)試會(huì)話上,對(duì)任務(wù)進(jìn)行管理,即:
PDB 通過控制中心可以利用 DBX/GDB 命令,以及 PDB 內(nèi)部命令對(duì)并行程序的任務(wù)進(jìn)行調(diào)試。
在 PDB 中使用 DBX/GDB 命令對(duì)并行程序進(jìn)行調(diào)試 PDB 啟動(dòng)以后,可以使用 DBX(在 AIX 系統(tǒng)上)/GDB(在 Linux 系統(tǒng)上)命令對(duì)并行程序進(jìn)行調(diào)試。下面通過在 IBM-Power 550, AIX61(AIX 系統(tǒng))/ SLES11(Linux 系統(tǒng))平臺(tái)上的簡(jiǎn)單實(shí)例演示如何在 PDB 中進(jìn)行設(shè)置斷點(diǎn),運(yùn)行程序,以及打印變量等操作。
清單 4. 在 AIX 系統(tǒng)上,使用 DBX 進(jìn)行調(diào)試:
(IBM-Power 550, AIX61(AIX 系統(tǒng) )) $ pdb ./mpihello --poe -procs 2 -hostfile ./host.list PDB -- Parallel Debugger for IBM Parallel Environment on AIX Current PDB debug session number is 655534. Be aware, only one console will connect to this session after startup, type 'pdb -c 655534' to connect more consoles to this session. At the prompt, enter any DBX command. Enter 'help' for more usage. (all) stop in main ( 設(shè)置斷點(diǎn)在源程序的 main 函數(shù) ) 0:1 | [1] stop in main (all) run ( 運(yùn)行程序 ) 0:1 | [1] stopped in main at line 10 in file "mpihello.c" ($t1) 0:1 | 10 MPI_Init(&argc,&argv); (all) list ( 顯示源代碼 ) 0:1 | 11 MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 0:1 | 12 MPI_Comm_rank(MPI_COMM_WORLD,&myrank); 0:1 | 13 MPI_Get_processor_name(processor_name,&namelen); 0:1 | 14 0:1 | 15 /* every process send msg to process 0 */ 0:1 | 16 strcpy(msg,"hello world!" ; 0:1 | 17 sprintf(msg,"hello world from %s",processor_name); 0:1 | 18 0:1 | 19 MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,0,99,MPI_COMM_WORLD); 0:1 | 20 (all) stop at 13 ( 設(shè)置斷點(diǎn)在源程序的第 13 行 ) 0:1 | [6] stop at "mpihello.c":13 (all) cont ( 繼續(xù)運(yùn)行程序 ) 0:1 | [6] stopped in main at line 13 in file "mpihello.c" ($t1) 0:1 | 13 MPI_Get_processor_name(processor_name,&namelen); (all) print numprocs ( 打印變量 numprocs 的值 ) 0:1 | 2 (all) print myrank ( 打印變量 myrank 的值 ) 0 | 0 1 | 1 |
在上例中,PDB 使用 DBX 命令設(shè)置了兩個(gè)斷點(diǎn),運(yùn)行了該并行程序,并打印了變量“numprocs”,及“myrank”的值。
清單 5. 在 Linux 系統(tǒng)上,使用 GDB 進(jìn)行調(diào)試:
(IBM-Power 550, SLES11(Linux 系統(tǒng) )) $ pdb ./mpihello --poe -procs 2 -hostfile ./host.list PDB -- Parallel Debugger for IBM Parallel Environment on Linux Current PDB debug session number is 2405. Be aware, only one console will connect to this session after startup, type 'pdb -c 2405' to connect more consoles to this session. At the prompt, enter any GDB command. Enter 'help' for more usage. (all) break main ( 設(shè)置斷點(diǎn)在源程序的 main 函數(shù) ) 0:1 | Breakpoint 1 at 0x100008a8: file mpihello.c, line 10. (all) run ( 運(yùn)行程序 ) 0:1 | Starting program: /u/ronglli/tests_linux/mpihello 0:1 | [Thread debugging using libthread_db enabled] 0 | [New Thread 0x4045f4b0 (LWP 2455)] 1 | [New Thread 0x4045f4b0 (LWP 2457)] 0 | [New Thread 0x4085f4b0 (LWP 2456)] 1 | [New Thread 0x4085f4b0 (LWP 245 ] 0:1 | 0:1 | Breakpoint 1, main (argc=1, argv=0xfffeef94) at mpihello.c:10 0:1 | 10 MPI_Init(&argc,&argv); (all) list ( 顯示源代碼 ) 0:1 | 5 int numprocs,myrank,i,namelen; 0:1 | 6 MPI_Status status; 0:1 | 7 char msg[128]; 0:1 | 8 char processor_name[MPI_MAX_PROCESSOR_NAME]; 0:1 | 9 0:1 | 10 MPI_Init(&argc,&argv); 0:1 | 11 MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 0:1 | 12 MPI_Comm_rank(MPI_COMM_WORLD,&myrank); 0:1 | 13 MPI_Get_processor_name(processor_name,&namelen); 0:1 | 14 (all) break 13 ( 設(shè)置斷點(diǎn)在源程序的第 13 行 ) 0:1 | Breakpoint 2 at 0x100008cc: file mpihello.c, line 13. (all) cont ( 繼續(xù)運(yùn)行程序 ) 0:1 | Continuing. 0 | [New Thread 0x476ff4b0 (LWP 2557)] 1 | [New Thread 0x476ff4b0 (LWP 255 ] 0 | [New Thread 0x4843f4b0 (LWP 2559)] 1 | [New Thread 0x4843f4b0 (LWP 2560)] 0 | [New Thread 0x48a4f4b0 (LWP 2562)] 1 | [New Thread 0x48a4f4b0 (LWP 2561)] 0 | [New Thread 0x4906f4b0 (LWP 2563)] 1 | [New Thread 0x4906f4b0 (LWP 2564)] 1 | 0:1 | Breakpoint 2, main (argc=1, argv=0xfffeef94) at mpihello.c:13 0:1 | 13 MPI_Get_processor_name(processor_name,&namelen); (all) print numprocs ( 打印變量 numprocs 的值 ) 0:1 | $1 = 2 (all) print myrank ( 打印變量 myrank 的值 ) 1 | $2 = 1 0 | $2 = 0 |
在上例中,PDB 使用 GDB 命令設(shè)置了兩個(gè)斷點(diǎn),運(yùn)行了該并行程序,并打印了變量“numprocs”,及“myrank”的值。
在 PDB 中使用 PDB 內(nèi)部命令對(duì)并行程序進(jìn)行調(diào)試 PDB 提供了內(nèi)部命令便于對(duì)并行程序進(jìn)行調(diào)試,例如“組操作”,“用戶自定義消息過濾準(zhǔn)則”,“消息聚合”,以及退出等。 組操作 PDB 支持對(duì)其并行程序的所有任務(wù)進(jìn)行組操作,即提供“group”命令,顯示組成員,創(chuàng)建一個(gè)包含一部分或全部任務(wù)的新組,刪除組,對(duì)組進(jìn)行賦值,加減操作等;并提供了“on”命令,來切換組名,選擇已定義的組為當(dāng)前組。在 PDB 一個(gè)調(diào)試會(huì)話啟動(dòng)后,PDB 就創(chuàng)建了預(yù)定義組“all”(包括了所有的任務(wù));“FILTERED”(包括所以針對(duì)上一條命令有消息輸出的任務(wù));以及“0”,“1”…“<num clinets -1>”(僅包括一個(gè)任務(wù))!癵roup”及“on”命令提供的操作如下所示:
清單 6. “group”命令提供的操作:
(all) help group Group clients group -- show all groups. group <name> -- show the group of <name>. group <name> = <clients> -- set group <name> to have <clients>. group <name> + <clients> -- add <clients> into group <name>. group <name> - <clients> -- delete <clients> from group <name>. <name>: the name of a group. <clients>: list of clients separated by space. <client>:<client> can be used for a range of clients. Group names can be used in the list too. Predefined groups are: 0, 1, 2, ..., <num clients - 1> representing individual clients, 'all' containing all clients, and Examples: group a = 0:2 4 -- Group a has clients 0,1,2,4 group b = 3 a -- Group b has clients 0,1,2,3,4 group a + b 5:7 -- Group a has clients 0,1,2,3,4,5,6,7 |
清單 7. “on”命令提供的操作:
(all) help on Switch client group on <group> -- Set current group to be <group>. Client commands are broadcast to all members in current group. |
下面通過 IBM-Power 550, AIX61(AIX 系統(tǒng))/ SLES11(Linux 系統(tǒng))平臺(tái)上的簡(jiǎn)單實(shí)例演示如何在 PDB 中進(jìn)行組操作,例如創(chuàng)建新組,刪除組,切換組等。
清單 8. 使用“group”及“on”命令進(jìn)行組操作:
(IBM-Power 550, AIX61(AIX 系統(tǒng) )/ SLES11(Linux 系統(tǒng) )) (all) group ( 使用 group 命令顯示組名 ) FILTERED: 0 1 2 3 4 5 6 7 all: 0 1 2 3 4 5 6 7 (all) group g1 = 0 1:4 ( 創(chuàng)建新組 ) (all) group g2 = 4 5 (all) group FILTERED: 0 1 2 3 4 5 6 7 all: 0 1 2 3 4 5 6 7 g1: 0 1 2 3 4 g2: 4 5 (all) group g1 - g2 (all) group FILTERED: 0 1 2 3 4 5 6 7 all: 0 1 2 3 4 5 6 7 g1: 0 1 2 3 g2: 4 5 (all) group g2 + g1 7 (all) group FILTERED: 0 1 2 3 4 5 6 7 all: 0 1 2 3 4 5 6 7 g1: 0 1 2 3 g2: 0 1 2 3 4 5 7 (all) list 0:7 | 1 #include "mpi.h" 0:7 | 2 0:7 | 3 main(int argc, char **argv) 0:7 | 4 { 0:7 | 5 int numprocs,myrank,i,namelen; 0:7 | 6 MPI_Status status; 0:7 | 7 char msg[128]; 0:7 | 8 char processor_name[MPI_MAX_PROCESSOR_NAME]; 0:7 | 9 0:7 | 10 MPI_Init(&argc,&argv); (all) on g1 ( 使用 on 命令切換當(dāng)前組 ) (g1) list 0:3 | 11 MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 0:3 | 12 MPI_Comm_rank(MPI_COMM_WORLD,&myrank); 0:3 | 13 MPI_Get_processor_name(processor_name,&namelen); 0:3 | 14 0:3 | 15 /* every process send msg to process 0 */ 0:3 | 16 strcpy(msg,"hello world!" ; 0:3 | 17 sprintf(msg,"hello world from %s",processor_name); 0:3 | 18 0:3 | 19 MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,0,99,MPI_COMM_WORLD); 0:3 | 20 |
用戶自定義消息過濾準(zhǔn)則 PDB 提供了用戶自定義消息過濾準(zhǔn)則,即提供“match”命令,對(duì)消息進(jìn)行過濾。
清單 9. “match”命令提供的操作:
(all) help match Filter client command outputs with regular expression match -- show last client command outputs. match <regexp> -- filter the last client command output with <regexp>. match <regexp> | match <regexp> | ... -- cascade style. Note: If you want to filter <command> output with <regexp>, you can use the system command. <command> | grep <regexp> -- filter <command> output with <regexp>. <command> | grep <regexp> | grep <regexp> | ... -- cascade style. <regexp>: regular expression surrounded by single(double) quotation marks <command>: client command. Examples: match 'Hello' -- Show lines that contain 'Hello' in last command outputs match 'Hello' | match 'World' -- Show lines that contain 'Hello' and 'World' in last command outputs match 'Hello|World' -- Show lines that contain 'Hello' or 'World' in last command outputs list | grep 'Hello' -- Show lines that contain 'Hello' in current command outputs list | grep 'Hello' | grep 'World' -- Show lines that contain 'Hello' and 'World' in current command outputs list | grep -E "Hello|World" -- Show lines that contain 'Hello' or 'World' in current command outputs This is available only in normal state. |
下面通過 IBM-Power 550, AIX61(AIX 系統(tǒng))/ SLES11(Linux 系統(tǒng))平臺(tái)上的簡(jiǎn)單實(shí)例演示如何在 PDB 中使用“match”命令,對(duì)消息進(jìn)行過濾。
清單 10. 使用“match”命令對(duì)消息進(jìn)行過濾:
(IBM-Power 550, AIX61(AIX 系統(tǒng) )/ SLES11(Linux 系統(tǒng) )) (all) list 0:7 | 1 #include "mpi.h" 0:7 | 2 0:7 | 3 main(int argc, char **argv) 0:7 | 4 { 0:7 | 5 int numprocs,myrank,i,namelen; 0:7 | 6 MPI_Status status; 0:7 | 7 char msg[128]; 0:7 | 8 char processor_name[MPI_MAX_PROCESSOR_NAME]; 0:7 | 9 0:7 | 10 MPI_Init(&argc,&argv); (all) match msg ( 使用 match 命令過濾與 msg 字符串匹配的消息 ) 0:7 | 7 char msg[128]; (all) list | grep MPI |grep Comm 0:7 | 11 MPI_Comm_size(MPI_COMM_WORLD,&numprocs); 0:7 | 12 MPI_Comm_rank(MPI_COMM_WORLD,&myrank); |
消息聚合(Message Aggregation) 在 PDB 中,不同任務(wù)中的相同的消息會(huì)被聚合,從而大幅度地增加了 PDB 的輸出消息的可讀性,減少了消息的冗余度。如下例: 0 | this is a test 1 | this is a test … 99 | this is a test |
以上輸出消息,會(huì)被聚合成一條消息:
綜上所述,PDB 提供了多種內(nèi)部命令,使得同時(shí)對(duì)多個(gè)任務(wù)進(jìn)行管理變得更加簡(jiǎn)單、方便;其輸出消息通過“用戶自定義消息過濾”、“消息聚合”等方法,增加了 PDB 的可用性
結(jié)束語(yǔ) 本文主要介紹了 IBM 發(fā)布的一種并行環(huán)境下的命令行調(diào)試工具 PDB,并詳細(xì)講解了 PDB V5.3 的特點(diǎn)及使用方法。通過 PDB,技術(shù)人員可以在 AIX/Linux 系統(tǒng)上,更加方便、高效地完成對(duì)并行程序的調(diào)試。
關(guān)于作者 李榮,IBM 中國(guó)軟件開發(fā)中心 HPC 部門的軟件工程師,主要從事高性能計(jì)算相關(guān)的工作。
http://www.ibm.com/developerworks/cn/aix/library/1106_lirong_pdb/index.html
|
|