# PP HW 4 Report Template > - Please include both brief and detailed answers. > - The report should be based on the UCX code. > - Describe the code using the 'permalink' from [GitHub repository](https://github.com/NTHU-LSALAB/UCX-lsalab). ## 1. Overview > In conjunction with the UCP architecture mentioned in the lecture, please read [ucp_hello_world.c](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/ce5c5ee4b70a88ce7c15d2fe8acff2131a44aa4a/examples/ucp_hello_world.c) 1. Identify how UCP Objects (`ucp_context`, `ucp_worker`, `ucp_ep`) interact through the API, including at least the following functions: - `ucp_init` - `ucp_worker_create` - `ucp_ep_create` ![image](https://hackmd.io/_uploads/r1xgwWNuT.png) - [ucp_init()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/ce5c5ee4b70a88ce7c15d2fe8acff2131a44aa4a/examples/ucp_hello_world.c#L575) : 有三個參數, 分別為params config context, params為題目所需的設定值, config 為[ucp_config_read()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/ce5c5ee4b70a88ce7c15d2fe8acff2131a44aa4a/examples/ucp_hello_world.c#L560)讀到的值, context則是config的handler - ucp_init`會呼叫`[ucp_init_version()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/src/ucp/api/ucp.h#L2061), 確定version, 並使用config 設置 context, 設置resource與aux (設置輔助傳輸層 例如rc_v等同於 rc_verbs ud_verbs(輔助傳輸層) 若rc_verbs建立不起來會使用ud_verbs) ,ucp_fill_config() : 會分配資源 (md (memory domain)) - [ucp_worker_create()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/ce5c5ee4b70a88ce7c15d2fe8acff2131a44aa4a/examples/ucp_hello_world.c#L587): 三個參數,context、worker_params、worker,worker會根據worker_params以及context設定,其中也有worker->context = context,這代表說每個worker只會對應到一個context, 一個context可與多個worker綁定 ep會與一個worker綁定。server會將用將address用socket傳給client, client peer去接 - [run_ucx_client()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/examples/ucp_hello_world.c#L629) 與 [run_ucx_server()](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/examples/ucp_hello_world.c#L633):其中會呼叫 `ucp_ep_create`需要三個參數,worker、ep_params、ep,其中ep會取決於你是run_ucx_client還是run_ucx_server, 在 `run_ucx_client` 時client會將 worker address 傳輸到server端 - [ucp_ep_create() ](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/src/ucp/core/ucp_ep.c#L1176) : 利用worker 創建 ep, 在run_ucx_client與run_ucx_server會分別設定要連線到的ep, ucp_ep_create是non-blocking的 - [ucp_tag_msg_recv_nbx](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/examples/ucp_hello_world.c#L483) 家的信箱,它用來接收發給你的訊息。 比如說: 在run_ucx_client中,你會用這個函數來收取伺服器發送的信息,就像查看郵箱裡有沒有新郵件一樣。 在run_ucx_server,這個函數則是用來取得客戶端發送的位址資訊。 這就好比伺服器透過它的「郵件」來知道客戶端在哪裡。 - [ucp_tag_send_nbx](https://github.com/NTHU-LSALAB/UCX-lsalab/blob/7c0362c97c8fe9cbeaacaac90271dde0210ac529/examples/ucp_hello_world.c#L266) 而這個函數,可以想像成你投遞郵件的動作。 它用來發送訊息到指定的地點。 例如: 在客戶端,你會用這個函數把你的地址資訊傳送給伺服器,就好像你在寄一封信告訴別人你在哪裡。 在伺服器端,一旦它透過 ucp_tag_msg_recv_nbx 函數拿到了客戶端的位址,就會建立一個連接點(透過 ucp_ep_create),然後用 ucp_tag_send_nbx 傳送訊息回客戶端。 這就像是伺服器收到你的信後,回了一封信給你。 - 總結 : 首先ucp_init會先初始化context, 並利用context去初始化worker, worker 會呼叫ucp_ep_create建立對應的endpoint, 最後進行傳輸(ucp_tag_send_nbx, ucp_tag_msg_recv_nbx) 2. What is the specific significance of the division of UCP Objects in the program? What important information do they carry? - `ucp_context` - `ucp_worker` - `ucp_ep` - `ucp_context` : 在`ucp_context.h`中,`typedef struct ucp_context`包括資訊: > 1.`uct component` : 負責管理不同類型的網路技術(如 InfiniBand、TCP)的具體實現。 > 2.`md` : “memory domain”理解為一種memory管理方式 , 不同的計算任務可能需要有效率地存取這些特殊的memory domain。 memory domain就是用來管理和優化這種記憶體存取的。 ...等等 > 基本上存 communication resource, endpoints, memory, temporary file storage 等等 總結 : 幫助管理和優化網路通訊和資料傳輸。透過這些component和資源的管理,UCX 能夠提供高效、靈活的通訊解決方案 - `ucp_worker` : 根據 `ucp_worker.h` 的`typedef struct ucp_worker`,可以發現它包括以下這些資料: > 1. `context` : 一個program 有一個context 並利用context 去創建worker > 2. `uuid 和 client_id` : 這些是用於網路連接和設定過程中的唯一識別碼。它們在建立網路連線和識別不同的 ucp_worker 實例時起到重要作用 > 3. `uct` : UCT 層處理更底層的網路通訊細節,ucp_worker 透過它來執行實際的網路操作 > 4. `req_mp 和 rkey_mp` : 用於管理和優化記憶體資源的使用。 req_mp 通常用於請求對象,而 rkey_mp 用於小的記憶體key。 > 5. `atomic_tls` : 用於指示哪些資源(傳輸層)可以用於atomic操作 > .... 紀錄ep的counter、keepalive等等 總結 : 負責具體的網路通訊任務。它包含了非同步處理、資源管理和網路操作所需的多種元件和配置 - `ucp_ep` : ucp_ep.h的struct ucp_ep,可以發現它包括以下這些資料: > worker、seq num、Transports for every lane..... >總結 : 在一個應用程式中,可以存在多個 Context,而在每個 Context 中又可以包含多個 Worker。這些 Worker 擁有它們各自的 Endpoints,透過這些端點,它們能夠相互溝通。在每個端點中,又會有多個 Lanes,用來處理特定的資料傳輸和通訊任務。 總結 : endpoint代表local worker到remote worker的連線。 remote worker可以在任何透過UCT層支援的通訊網路可達的地方創建 ucp_context_h: 資源隔離與管理:情境提供了一種方式來隔離和管理硬體資源和記憶體資源。 在同一個program中可以建立多個context,這樣就能夠在不同的context中獨立管理資源,減少資源衝突和依賴。 應用程式的靈活性:不同的應用程式或應用程式的不同部分可能需要不同的資源配置或最佳化。 透過使用多個context,可以根據需要自訂資源配置。 ucp_worker_h: 通訊狀態管理:工作器代表通訊狀態和網路資源,是處理訊息和網路事件的實體。 它允許進行細粒度的通訊控制和調度。 multi thread支援:雖然從multi thread使用單一worker可能會因lock競爭而導致效能下降,但設計上支援multi thread可以提供更大的靈活性,允許應用根據需求來平衡效能。 ucp_ep_h: point to point連線:endpoint代表了一個點對點的連線。 透過將連接抽象化為端點,可以更有效地管理和最佳化每個連接。 網路拓撲適應性:端點可以適應不同的網路拓撲和通訊需求,例如,在不同主機、同一主機或跨不同類型的網路設備進行通訊。 3. Based on the description in HW4, where do you think the following information is loaded/created? - `UCX_TLS` > 我認為是存在context中, context應該記錄所有可能的TLS, 以便未來創建worker 與worker創建end point - TLS selected by UCX > endpoint 是一個交接處, 所以必須知道不同worker需要的資源, 才能選定TLS ## 2. Implementation > Describe how you implemented the two special features of HW4. - ``ucs/config/parser.c``這個file裡面的ucs_config_parser_print_opts print Line 1的資訊 ```c++= // TODO: PP-HW4 if (flags & UCS_CONFIG_PRINT_TLS) { for (f = fields; !ucs_config_field_is_last(f); ++f) { if(strcmp(f->name,"TLS") == 0){ break; } } table_prefix_elem.prefix = table_prefix ? table_prefix : ""; ucs_list_add_tail(&prefix_list, &table_prefix_elem.list); ucs_config_parser_print_field(stream, opts, prefix, &prefix_list, f->name, f, flags, NULL); } ``` - 在``src/ucp/core/ucp_worker.c``中``ucp_worker_print_used_tls`` 新增 *config variable ```c++= static void ucp_worker_print_used_tls(ucp_worker_h worker, ucp_worker_cfg_index_t cfg_index) { const ucp_ep_config_key_t *key = &ucs_array_elem(&worker->ep_config, cfg_index).key; ucp_context_h context = worker->context; UCS_STRING_BUFFER_ONSTACK(strb, 256); ucp_lane_map_t tag_lanes_map = 0; ucp_lane_map_t rma_lanes_map = 0; ucp_lane_map_t amo_lanes_map = 0; ucp_lane_map_t stream_lanes_map = 0; ucp_lane_map_t am_lanes_map = 0; ucp_lane_map_t ka_lanes_map = 0; int rma_emul = 0; int amo_emul = 0; int num_valid_lanes = 0; ucp_lane_index_t lane; ucs_status_t status; ucp_config_t *config; // modify .... if (status == UCS_OK) {//modify ucp_config_print(config,stdout,NULL,UCS_CONFIG_PRINT_TLS ); //Line1 fprintf(stdout,"%s\n",ucs_string_buffer_cstr(&strb)); //Line2 } } ``` - 在 ``src/ucs/config/types.h``中: ```c++= typedef enum { UCS_CONFIG_PRINT_CONFIG = UCS_BIT(0), UCS_CONFIG_PRINT_HEADER = UCS_BIT(1), UCS_CONFIG_PRINT_DOC = UCS_BIT(2), UCS_CONFIG_PRINT_HIDDEN = UCS_BIT(3), UCS_CONFIG_PRINT_COMMENT_DEFAULT = UCS_BIT(4), UCS_CONFIG_PRINT_TLS = UCS_BIT(5) //modify } ucs_config_print_flags_t; ``` 1. Which files did you modify, and where did you choose to print Line 1 and Line 2? - 我更改了 ``ucs/config/parser.c``, ``src/ucp/core/ucp_worker.c``, ``src/ucs/config/types.h`` - 在加上UCS_CONFIG_PRINT_TLS flag以後, 他會印出許多資訊(env variable), 然而因為我們只需要TLS資料, 若不是TLS相關的就忽略掉 - 我在ucp_worker.c的ucp_worker_print_used_tls中印出。 2. How do the functions in these files call each other? Why is it designed this way? - ucp_worker.c 與 parser.c 的關係: 在 ``ucp_worker.c`` 檔案中,某些函數會呼叫 ``parser.c``, ``type.h``用來定義UCS_CONFIG_PRINT_TLS。 ``types.h`` 的作用: types.h 檔案主要用於定義各種類型和巨集,例如: 多定義UCS_CONFIG_PRINT_TLS。 這些定義在整個 UCX 原始碼中被廣泛使用。 ucp_worker_print_used_tls 函數的呼叫: 在 ``ucp_worker.c`` 中的 ucp_worker_print_used_tls 函數會呼叫 ``ucp_context.c`` 中的 ucp_config_print。 這是因為config與context是一對一的關係。 接著,ucp_config_print 會呼叫 ``parser.c`` 中的 ucs_config_parser_print_opts 函數。 這個函數負責print出對應的設定資訊。 3. Observe when Line 1 and 2 are printed during the call of which UCP API? ```c++= ucp_ep_create => ucp_ep_create_to_sock_addr => ucp_ep_init_create_wireup => ucp_worker_get_ep_config => ucp_worker_print_used_tls ``` 4. Does it match your expectations for questions **1-3**? Why? - 是, 因為Line 1的資訊是從context中取得的,而這個設定檔是在建立context物件的時候就已經確定下來的。 根據前一個問題的說明,Line 2的確是在創建end point的過程中就被印出來的。 5. In implementing the features, we see variables like lanes, tl_rsc, tl_name, tl_device, bitmap, iface, etc., used to store different Layer's protocol information. Please explain what information each of them stores. - lanes : lanes 代表 endpoint 往remote 的不同 channel (TCP, infinitBand....) - tl_rsc : tl_rsc 是 UCX中代表transport layer資源,用於最佳化通訊效率 包括 : hardware name, protocol name ...。 - tl_name : 資源的名字 - tl_device : 資源的裝置種類。 - bitmap : 用來標記Transport Layer的資源的使用情況 - iface : 用來負責處理底層網路或硬體的通訊協議, 例如 : 使用次數,Callback ID,未完成的request數量 - 可透過``ucp_worker_add_resource_ifaces``, 這個可以將資源的interface打開, 他會去確認bitmap中可用資源, 如果有開資源(worker)可直接使用, 如果沒有, 則會選擇最好的資源並紀錄於bitmap中 ## 3. Optimize System 1. Below are the current configurations for OpenMPI and UCX in the system. Based on your learning, what methods can you use to optimize single-node performance by setting UCX environment variables? ``` ------------------------------------------------------------------- /opt/modulefiles/openmpi/4.1.5: module-whatis {Sets up environment for OpenMPI located in /opt/openmpi} conflict mpi module load ucx setenv OPENMPI_HOME /opt/openmpi prepend-path PATH /opt/openmpi/bin prepend-path LD_LIBRARY_PATH /opt/openmpi/lib prepend-path CPATH /opt/openmpi/include setenv UCX_TLS ud_verbs setenv UCX_NET_DEVICES ibp3s0:1 ------------------------------------------------------------------- ``` ## latency - 執行 mpiucx -x UCX_TLS=shm -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_latency ```c++= [pp23s64@apollo31 hw4]$ mpiucx -x UCX_TLS=shm -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_latency UCX_TLS=shm 0x55fc0cb82da0 self cfg#0 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55fc0cb82da0 intra-node cfg#1 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55bc4f91ada0 self cfg#0 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55bc4f91ada0 intra-node cfg#1 tag(sysv/memory cma/memory) # OSU MPI Latency Test v7.3 # Size Latency (us) # Datatype: MPI_CHAR. 1 0.24 2 0.23 4 0.24 8 0.25 16 0.23 32 0.28 64 0.27 128 0.44 256 0.44 512 0.47 1024 0.55 2048 0.71 4096 1.24 8192 1.70 16384 3.00 32768 4.89 65536 8.70 131072 24.38 262144 37.72 524288 68.86 1048576 142.52 2097152 290.89 4194304 938.68 ``` - 執行mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_latency ```c++= [pp23s64@apollo31 UCX-lsalab]$ mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_latency UCX_TLS=ud_verbs 0x563984624e40 self cfg#0 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x55fc54dfadb0 self cfg#0 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x563984624e40 intra-node cfg#1 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x55fc54dfadb0 intra-node cfg#1 tag(ud_verbs/ibp3s0:1) # OSU MPI Latency Test v7.3 # Size Latency (us) # Datatype: MPI_CHAR. 1 1.63 2 1.61 4 1.61 8 1.82 16 1.77 32 1.80 64 2.08 128 1.98 256 3.63 512 3.92 1024 4.58 2048 6.10 4096 10.58 8192 11.43 16384 16.91 32768 22.71 65536 38.61 131072 64.50 262144 128.52 524288 237.03 1048576 460.26 2097152 920.90 4194304 1868.95 ``` ## bandwidth - 執行 mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_bw ```c++= [pp23s64@apollo31 UCX-lsalab]$ mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_bw UCX_TLS=ud_verbs 0x559b9d1e9e90 self cfg#0 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x55a2cde70e10 self cfg#0 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x55a2cde70e10 intra-node cfg#1 tag(ud_verbs/ibp3s0:1) UCX_TLS=ud_verbs 0x559b9d1e9e90 intra-node cfg#1 tag(ud_verbs/ibp3s0:1) # OSU MPI Bandwidth Test v7.3 # Size Bandwidth (MB/s) # Datatype: MPI_CHAR. 1 2.09 2 4.29 4 8.66 8 17.29 16 33.84 32 68.03 64 125.92 128 235.78 256 342.78 512 655.62 1024 1099.07 2048 1650.20 4096 1334.84 8192 1960.04 16384 2234.93 32768 2347.25 65536 2185.16 131072 2431.08 262144 2395.80 524288 2451.15 1048576 2309.49 2097152 2439.82 4194304 2348.74 ``` - 執行 mpiucx -x UCX_TLS=shm -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_bw ```c++= [pp23s64@apollo31 UCX-lsalab]$ mpiucx -x UCX_TLS=shm -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_bw UCX_TLS=shm 0x55a062c13e90 self cfg#0 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55a062c13e90 intra-node cfg#1 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55873fe39e00 self cfg#0 tag(sysv/memory cma/memory) UCX_TLS=shm 0x55873fe39e00 intra-node cfg#1 tag(sysv/memory cma/memory) # OSU MPI Bandwidth Test v7.3 # Size Bandwidth (MB/s) # Datatype: MPI_CHAR. 1 8.93 2 15.73 4 30.56 8 61.42 16 114.40 32 242.70 64 481.01 128 552.95 256 1076.90 512 1882.37 1024 3077.25 2048 4717.93 4096 6832.44 8192 8406.54 16384 4041.36 32768 5665.51 65536 7394.18 131072 8746.21 262144 7436.00 524288 7823.17 1048576 8133.06 2097152 7931.72 4194304 7410.03 ``` - 綜合以上結果, 符合我的預期, 因為是single node, 若不使用網路傳輸, 使用share memory速度會較快, 所以執行時間較快, 而因為我們使用share memory傳輸所以bandwidth也提高許多 > Please use the following commands to test different data sizes for latency and bandwidth, to verify your ideas: ```bash module load openmpi/4.1.5 mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_latency mpiucx -n 2 $HOME/UCX-lsalab/test/mpi/osu/pt2pt/standard/osu_bw ``` ### Advanced Challenge: Multi-Node Testing This challenge involves testing the performance across multiple nodes. You can accomplish this by utilizing the sbatch script provided below. The task includes creating tables and providing explanations based on your findings. Notably, Writing a comprehensive report on this exercise can earn you up to 5 additional points. - For information on sbatch, refer to the documentation at [Slurm's sbatch page](https://slurm.schedmd.com/sbatch.html). - To conduct multi-node testing, use the following command: ``` cd ~/UCX-lsalab/test/ sbatch run.batch ``` ## 4. Experience & Conclusion 1. What have you learned from this homework? - 我學到了UCX基本操作, 在trace code過程讓我更深刻了解UCX內部資料結構,與如何傳輸, 雖然過程艱辛, 很多疑問, 但整體來說學到很多 2. Feedback (optional) - 因為學期末, 有許多final exam 與 final project, 所以沒有花太多時間在hw4上, 但是非常感謝實驗室的同學與岱蔚願意與我討論, 讓我們彼此間更有效率的掌握本次作業