# PIConGPU ## 關於 PIC 軟體 PIC 的功能,是模擬一個空間中的粒子運動,並藉此計算出電場、磁場或是輻射 - 模擬的整個空間大小,稱為 **domain** - 一個 domain 會被切成多個網格 (**grid**) - PIC 做的事情就是計算每個網格中的粒子分布情況 - 每一次更新網格,叫做一個 step;一個 step 代表一小段物理時間(e.g., 10ns) - 對於相同內容的模擬,每一個 step 做的運算是相同的 - 但根據國展老師的經驗,因為 domain 中的粒子總數可能會變化,所以有可能隨著模擬的 step 越多 (粒子總量越多),計算量越大 - **賽後經驗**: 也可能隨著模擬時間、粒子密度的分布也有所變化,導致不同方向所需的計算資源(GPU 數量)有變化 PIC 的軟體,通常是給一個基礎的運算框架 - 一些固定的物理常數 (光速、電荷...) - 一些可調的實驗參數 (磁場、外加能量、邊界條件...) - 一個固定的運算框架 - Grid 怎麼切 - 每個 step 做哪些事情 - 粒子間怎麼交互作用 粒子模擬中,大部分的參數都和物理相關,會影響到模擬結果的物理表現 - 進行的模擬內容相同的情況下,不論參數如何調整,所需運算量應該都相同 - 之前上課的教授說,這些物理面的參數就只是參與運算的一個數字,不影響效能 (可以想成 1000 * a 和 10000 * a 複雜度一樣) - 會影響運算量的有 - 網格數量 - VSim: domain 大小/網格大小 - PIConGPU: grid_x * grid_y * grid_z - step 數量 (影響總時間) 粒子模擬是個很複雜的應用,所以 PIC 軟體本身不會包含所有運算 - 只會提供通用的框架、以及必要的運算(基本物理的運算) - 每個 user 要模擬的環境(外加電場/磁場、雷射源...)都不一樣,所以 PIC 軟體會讓 user 可以插入自己寫的運算模組 - VSim: user 可插入自己寫的 Python 檔案 (所以不需要重新編譯) - PIConGPU: 用 C/C++ 寫,所以如果有運算內容相關的設定,就需要重新編譯 :::success **PIConGPU 在這方面的設計** - PIC 模擬,需要能讓 user 改動程式碼 - 所以 PIConGPU 不是直接 build 出來一個通用的軟體,然後吃不同的輸入檔案 - 做的模擬不一樣,跑的程式碼其實也不太像同 (只有大架構一樣) - PIConGPU 提供方便 build 的工具 (底層還是 CMake),讓 user 改好東西後,用它的指令重新 build - 有些要傳進去 Cmake 的參數會以環境變數的形式存在 - 操作上會和以往的軟體不太一樣,但其實做的事情是差不多的 - 所以讀文件時覺得怪怪的是正常的 ::: ## 安裝 參考官方範例: 1. 先做這個 [PIConGPU - Install](https://github.com/ComputationalRadiationPhysics/picongpu/blob/dev/INSTALL.rst) 2. 再做這個: [PIConGPU - Usage](https://github.com/ComputationalRadiationPhysics/picongpu/blob/dev/USAGE.rst) 裡面有提到大量 dependency,建議全部啟用,才有辦法跑它執行的模擬範例 - 只有 ROCm 可省略,因為我們不是 AMD GPU/CPU - ISAAC 也可以省略,確定本次競賽用不到 ## 安裝必要工具 - git ``` sudo apt install git ``` - rsync ``` sudo apt install rsync ``` - 編譯器 ``` sudo apt install build-essential gfortran ``` - Cmake (3.22.0+) ``` # For ubuntu22 sudo apt install cmake file cmake-curses-gui ``` - **注意**: Ubuntu20 上,用 apt 載到的 cmake 版本過舊,要用 snap 安裝 ``` sudo snap install cmake --classic ``` ## 準備 dependency 這邊的所有 dependency 可以選擇 build from source 或 apt 安裝,但是要注意 apt 上可能裝到過舊的版本 dependency 裝好還需要設定額外的**環境變數**,這些環境變數會在編譯 PIC 時用到 ### MPI (2.3+) - 對應 OpenMPI 版本須高於 1.7 - 注意: MPI 版本不等於 OpenMPI 版本或 - **建議**: - 後面用到的 lib 也用到 MPI,但是使用到 MPI3.0 棄用的 API - 這邊就準備 Openmpi 2.1.6 就可以了 - 建議使用的 MPI 要啟用 CUDA (GPU aware) - **環境變數** ``` export MPI_ROOT=path/to/your/mpi ``` :::info **建議** - 可以順便 module load openmpi,這樣後面的套件,如果可以 MPI 優化的話,就會自動偵測到 ::: ### Boost (1.74.0+) - For Ubuntu22 ``` sudo apt install libboost-program-options-dev libboost-atomic-dev ``` - For 20 (build from source) ```= wget https://archives.boost.io/release/1.74.0/source/boost_1_74_0.tar.gz tar xf boost_1_74_0.tar.gz cd boost_1_74_0 ./bootstrap.sh --with-libraries=atomic,program_options --prefix=<Install path> ./b2 cxxflags="-std=c++17" -j 8 && sudo ./b2 install ``` - **環境變數** (只有 build from source 需要) ``` export CMAKE_PREFIX_PATH=<Install path>:$CMAKE_PREFIX_PATH ``` ### CUDA 安裝好 CUDA 後,須設定**環境變數** ``` export CMAKE_PREFIX_PATH=<CUDA_INSTALL>:$CMAKE_PREFIX_PATH ``` ### libpng (1.2.9+) - libpng 需要 zlib,下方指令一次安裝 ``` sudo apt install zlib1g-dev libpng-dev ``` ### pngwriter ```= git clone -b 0.7.0 https://github.com/pngwriter/pngwriter.git mkdir ./pngwriter/build && cd ./pngwriter/build cmake .. -DCMAKE_INSTALL_PREFIX=<Install path> make -j sudo make install ``` - **環境變數** ``` export CMAKE_PREFIX_PATH=<Install path>:$CMAKE_PREFIX_PATH ``` ### HDF5 (for openPMD API) ```= wget "https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.1/src/CMake-hdf5-1.10.1.tar.gz" tar xf CMake-hdf5-1.10.1.tar.gz cd CMake-hdf5-1.10.1/hdf5-1.10.1 mkdir build && cd ./build cmake .. -DHDF5_BUILD_CPP_LIB=OFF -DHDF5_ENABLE_PARALLEL=ON --install-prefix=<Install path> make -j sudo make install ``` - **環境變數** ``` export CMAKE_PREFIX_PATH=<Install path>:$CMAKE_PREFIX_PATH ``` - 這是為了後面編譯 openPMD API 的時候,可以偵測到有 HDF5 ### ADIOS2 (for openPMD API) ```= git clone https://github.com/ornladios/ADIOS2.git mkdir ./ADIOS2/build && cd ./ADIOS2/build cmake .. -DADIOS2_BUILD_EXAMPLES=ON --install-prefix=<Install path> make -j sudo make install ``` - **環境變數** ``` export CMAKE_PREFIX_PATH=<Install path>:$CMAKE_PREFIX_PATH ``` - 這是為了後面編譯 openPMD API 的時候,可以偵測到有 ADIOS2 ### openPMD API ```= git clone -b 0.15.0 https://github.com/openPMD/openPMD-api.git cd openPMD-api mkdir build && cd build cmake .. -DCMAKE_INSTALL_PREFIX=<Install path> \ -DopenPMD_USE_MPI=ON -DopenPMD_USE_ADIOS2=ON -DopenPMD_USE_HDF5=ON make -j sudo make install ``` - **環境變數** ``` export CMAKE_PREFIX_PATH=<Install path>:$CMAKE_PREFIX_PATH ``` ### c-blosc - 唯一的真 optional ``` sudo apt-get install libblosc-dev ``` - 我還沒測試過,不確定能不能用 ### FFTW3 ```= wget -O fftw-3.3.10.tar.gz http://fftw.org/fftw-3.3.10.tar.gz tar -xf fftw-3.3.10.tar.gz mkdir fftw-3.3.10/build && cd fftw-3.3.10/build ../configure --prefix=<Install path> make -j sudo make install ``` - **環境變數** ``` export FFTW3_ROOT=<Install path> export LD_LIBRARY_PATH=$FFTW3_ROOT/lib:$LD_LIBRARY_PATH ``` ## 下載 PIConGPU ``` git clone https://github.com/ComputationalRadiationPhysics/picongpu.git ``` - 環境變數 ```= export PICSRC=$PWD/picongpu export PIC_EXAMPLES=$PICSRC/share/picongpu/examples export PATH=$PATH:$PICSRC export PATH=$PATH:$PICSRC/bin export PATH=$PATH:$PICSRC/src/tools/bin export PYTHONPATH=$PICSRC/lib/python:$PYTHONPATH ``` ## 範例模擬 ### 前置作業 - 選擇一個存放編譯結果的目錄 (不可以在 PIConGPU 的 source code 中) ``` export SCRATCH=<Path of PIC runtime> ``` - 建立兩個目錄 ```= # Input file mkdir $SCRATCH/picInputs # simulation output mkdir $SCRATCH/runs ``` ### 建立 Inputfile 這邊使用官方範例 ```= pic-create $PIC_EXAMPLES/LaserWakefield $SCRATCH/picInputs/myLWFA cd $SCRATCH/picInputs/myLWFA ``` ### 編譯 ``` pic-build ``` ### 執行模擬 ``` tbg -s bash -c etc/picongpu/1.cfg -t etc/picongpu/bash/mpiexec.tpl $SCRATCH/runs/lwfa_001 ``` - 執行結果存在 `runs/lwfa_001` :::warning - 如果執行到一半失敗,`runs/lwfa_001` 也會建立 - 如果同樣指令重新執行,會顯示路徑已經存在的錯誤 - 可以先將 `runs/lwfa_001` 刪除,就可以再跑一次 (或是換個名字,例如 `runs/lwfa_XXX`) ::: ### 參數 #### 模擬大小和 step 數量 ![image](https://hackmd.io/_uploads/SkGIaax_0.png) - TBG_gridSize: 模擬的空間大小 (domain) - TBG_steps: 模擬的 step 數量 - TBG_devices_x/y/z: 每個維度上使用的 GPU 數量 - 三個數字相乘要等於總 GPU 數量 #### Dump - 模擬的過程,會每隔幾個 step 就存一個檔案,但是這個存檔的大小超大 - 中間的間隔可以在 `$SCRATCH/picInputs/myLWFA/etc/picongpu/1.cfg` 中設定 - 將設定檔中的所有 `period` 參數都改大,就可以減少輸出檔案的大小 ![image](https://hackmd.io/_uploads/Hypon6lO0.png) - 預設是 100,這邊我全部改 500 ## Benchmark ### 2080ti * 1 - 260.43sec ![image](https://hackmd.io/_uploads/SJ-mxmeuR.png) ### 2080ti * 2 - 198.42 sec ![image](https://hackmd.io/_uploads/BkkSWQxOR.png) ### V100 * 8 (1, 1, 8) - 44.315 sec ![image](https://hackmd.io/_uploads/SJk2CbCFC.png) ### V100 * 8 (1, 8 ,1) - 29.180 sec ![image](https://hackmd.io/_uploads/SkKpRZCKR.png) ### V100 * 8 (8, 1, 1) - 52.484 sec ![image](https://hackmd.io/_uploads/rkzgyfAKR.png) ### V100 * 8 (2, 2, 2) - 33.708 sec ![image](https://hackmd.io/_uploads/r1gBfJGAYR.png) ### V100 * 8 (1, 2, 4) - 34.799 sec ![image](https://hackmd.io/_uploads/SyK4kfAFR.png) ### V100 * 8 (1, 4, 2) - 31.523 sec ![image](https://hackmd.io/_uploads/S1SPkMCFC.png) ### V100 * 8 (2, 1, 4) - 36.292 sec ![image](https://hackmd.io/_uploads/rk7uJfRFA.png) ### V100 * 8 (2, 4, 1) - 34.85 sec ![image](https://hackmd.io/_uploads/ryeRumPYC.png) ### V100 * 8 (2, 2, 2) - 41.226 sec ![image](https://hackmd.io/_uploads/ByRknmDKC.png) ### V100 * 8 (2, 1, 4) - 52.12 sec ![image](https://hackmd.io/_uploads/Sy6Cj7DK0.png) ### V100 * 8 (1, 4, 2) - 37.397 sec ![image](https://hackmd.io/_uploads/Syt7aXwKR.png) ### V100 * 8 (1, 8, 1) - 33.601 sec ![image](https://hackmd.io/_uploads/SkD46QPKR.png) ### V100 * 16 (4, 4, 1) - 30.996 sec ![image](https://hackmd.io/_uploads/Sy6j9qnYA.png) ### V100 * 16 (2, 4, 2) - 26.48 sec ![image](https://hackmd.io/_uploads/H1TF5cnYR.png) ### V100 * 16 (2, 4, 2)B - 23.550 sec ![image](https://hackmd.io/_uploads/H17lh93YR.png) ### V100 * 16 (1, 16, 1) - 24.388 sec ![image](https://hackmd.io/_uploads/SJr6q53KA.png) ### V100 * 16 (1, 16, 1)B - 22.319 sec ![image](https://hackmd.io/_uploads/BJhRcq3FC.png) # Runtime 參數 Job 指令 ``` tbg -s <啟動方式> -c <cfg檔> -t <tpl檔> <output path> ``` - 啟動方式: 執行 job 的方法 - bash: 直接在 shell 裡面執行 - sbatch: submit slurm job - cfg: PIConGPU 層級的參數 - 例如: 模擬的空間大小、模擬的 step 數量、每個方向使用的 GPU 數量 - tpl: 環境層級的參數 - 例如 MPI 參數、Slurm 參數、環境變數 ## CFG 有打 * 是我覺得可能跟效能相關 (且不影響結果) ### Required Variables #### TBG_wallTime ``` TBG_wallTime="1:00:00" ``` 好像是時間上限的樣子 #### *TBG_devices_x/y/z ``` TBG_devices_x=1 TBG_devices_y=1 TBG_devices_z=1 ``` - 每個方向上使用的 GPU 數量 - 相乘必須等於使用的 GPU 總數 #### TBG_gridSize、TBG_steps ``` TBG_gridSize="192 1024 192" TBG_steps="2000" ``` - 模擬的空間大小 - 模擬的步數 #### TBG_periodic ``` TBG_periodic="--periodic 0 0 1" ``` - 不知道什麼的週期,需要有人查一下 >在你的例子中,TBG_periodic="--periodic 1 0 1" 表示: >X 維度是週期性的 (1)。 >Y 維度不是週期性的 (0)。 >Z 維度是週期性的 (1)。 >這意味著,在 X 和 Z 維度上,粒子離開模擬空間的一側時會進入對應的另一側,類似於一個無窮長的環狀空間。而 Y 維度則有固定的邊界,粒子到達邊界時會反彈或消失,取決於其他的邊界條件設定。這樣的設計可以用來模擬某些特定的物理現象,比如在長波長尺度上假設空間的無限延伸性。 > By ChatGPT ### Optional Variables - 範例中,這一段的參數都在設定和 output 相關的參數 - PIConGPU 的 output 支援多種格式,每個格式都有對應的模組負責處理 - 這邊比較重要的是輸出週期 (多少個 step 輸出一次) #### TBG_pngYX ``` TBG_pngYX="--e_png.period 100 \ --e_png.axis yx --e_png.slicePoint 0.5 \ --e_png.folder pngElectronsYX" ``` - Output 是 YX 平面的渲染圖 - `--e_png.period 100` 表示 100 step 輸出一次 #### 其他模組 - 其他模組各有各的參數 - 應該不影響效能(time per step),但是會影響輸出結果和總執行時間 (輸出寫檔會很久) **建議** - 測試的時候可以只開 pngYX 的模組 - 預設設定長這樣 ``` TBG_plugins="!TBG_pngYX \ !TBG_e_histogram \ !TBG_e_PSypy \ !TBG_e_macroCount \ !TBG_openPMD" ``` - 可以改這樣,減少輸出時間和節省硬碟空間 ``` TBG_plugins="!TBG_pngYX" ```