效能儀器精化自動化框架PIRA解決了使用 Score-P 時為未知程式碼庫產生合理效能測量的耗時任務。欲了解更多信息,請參閱我們的論文:
[PI18] | 揚-派翠克·萊爾、亞歷山大·哈克、克里斯蒂安·比紹夫。 PIRA:效能儀表精化自動化。第五屆 ACM SIGPLAN 軟體工程和平行運算系統人工智慧和經驗方法 (AI-SEPS) 國際研討會,第 1-10 頁,ACM,2018 年。 |
[PI19] | 揚-派翠克·萊爾、亞歷山德魯·卡洛托尤、克里斯蒂安·比肖夫、菲利克斯·沃爾夫。用於經驗性能建模的自動儀器細化。在國際程式設計和效能視覺化工具研討會 (ProTools)中,第 40-47 頁,IEEE,2019。 |
[PI21] | 彼得·阿茲特、雅尼克·菲施勒、揚-帕特里克·萊爾、克里斯蒂安·比肖夫。 MPI 應用中的自動低開銷負載不平衡偵測。 Euro-Par 2021:並行處理。計算機科學講義,第 12820 卷,第 19-34 頁,Springer,2021 年。 |
PIRA 運行以下四個階段(迭代 2-4 個階段):
PIRA 支援函數的編譯時和執行時間過濾,包括透過自動產生的包裝器對 MPI 函數進行執行時間過濾。在編譯時過濾中,僅在編譯時檢測所需的函數,從而顯著降低整體測量影響。相反,在運行時過濾中,編譯器將檢測掛鉤插入到目標應用程式的每個函數中,並且過濾在運行時發生。
PIRA 需要 CMake (>=3.16)、Clang/LLVM 10、Python 3、Qt5 和 OpenMPI 4。
如果您想在無法存取網際網路的環境中建立 PIRA,請參閱resources/build_submodules.sh
腳本,並根據您的需求進行調整。
克隆 PIRA 儲存庫。
$> git clone https://github.com/tudasc/pira
$> cd pira
其次,使用提供的腳本建立依賴的子模組,或傳遞不同選項的值(透過-h
查看可用選項的使用資訊)。所有下載和建置的檔案將放置在external/src/
中,而所有安裝將放置在external/install/
中。指定為編譯 PIRA 外部而產生的編譯進程數。該腳本將下載 PIRA 的預設版本的依賴項。這些版本也在我們的 CI 中進行了測試,預計可以正常工作。
$> cd resources
$> ./build_submodules.sh -p <ncores>
最後一步,建置腳本會將子模組的安裝路徑寫入檔案resources/setup_paths.sh
中。如果您希望重建 PIRA,請記住git restore
此檔案。
我們還提供了一個(實驗性) Dockerfile
來建立 PIRA 並進行嘗試。
$> podman build -t pira:master -f docker/Dockerfile .
當在容器內執行時,例如整合測試,請按以下方式呼叫腳本。
$> cd resources
$> . setup_paths.sh
$> cd ../test/integration/GameOfLife # Example test case
# By default PIRA will look into $HOME/.local, which is not currently existent in the docker
# XDG_DATA_HOME signals where to put the profiling data PIRA generates
$> XDG_DATA_HOME=/tmp ./run.sh
有關如何使用 PIRA 的完整範例,請查看/test/integration/*
資料夾中的run.sh
腳本。 GameOfLife
資料夾及其測試案例是一個潛在的良好起點。
首先,透過在resources
資料夾中取得腳本來設定所需的路徑。
$> cd resources/
$> . setup_paths.sh
然後,您可以使用./test/integration/GameOfLife
資料夾中提供的run.sh
腳本在 Conway 的 Game of Life 的非常簡單的實作上執行 PIRA 範例應用程式。
$> cd ./test/integration/GameOfLife
$> ./run.sh
該腳本從一開始就執行所需的所有步驟,即為新的目標程式碼準備所有元件,以最終呼叫 PIRA。在後續部分中,將更詳細地解釋這些步驟。步驟是:
config
設定檔的路徑(必要參數)--config-version [1,2]
PIRA 配置的版本,2 是預設值,鼓勵使用; 1 已棄用。--runtime-filter
使用運行時過濾,預設為 false。在編譯時過濾中,函數不在編譯時進行檢測,顯著降低了總體測量影響,但需要在每次迭代中重建目標。相反,透過執行時間過濾,編譯器會在目標應用程式的每個函數中插入偵測掛鉤。--iterations [number]
Pira 迭代次數,預設值為 3。--repetitions [number]
測量重複次數,預設值為 3。--tape
應寫入(有點廣泛)日誌磁帶的位置。--extrap-dir
放置 Extra-p 資料夾結構的基本目錄。--extrap-prefix
Extra-P 前綴,應該是字元序列。--version
列印 PIRA 安裝的版本號--analysis-parameters
包含 PGIS 分析參數的設定檔路徑。 Extra-P 和 LIDe 模式均需要。--slurm-config [path to slurm cfg file]
允許在 slurm 叢集上執行目標程式碼。需要 slurm 設定檔。請參閱本節以了解更多資訊。 --hybrid-filter-iters [number]
在 [number] 次迭代後重新編譯,在其間使用執行時過濾。--export
將產生的 Extra-P 模型和資料集大小附加到目標的 IPCG 檔案中。--export-runtime-only
需要--export
;僅將所有重複的運行時間中值附加到函數。僅在不使用 Extra-P 時可用。--load-imbalance-detection [path to cfg file]
啟用並配置負載不平衡偵測模式。請閱讀本節以獲取更多資訊。 PIRA 使用原始碼資訊來建立初始工具並決定在迭代細化期間將哪些功能新增至工具。它提供了一個基於 Clang 的呼叫圖工具,可以收集所有必需的資訊並將資訊輸出到.json
檔案中。您可以在子目錄./extern/src/metacg/cgcollector
中找到cgcollector
工具。 PIRA 要求呼叫圖檔採用版本 2 (MetaCG v2) 中的 MetaCG 檔案格式。
有關 CGCollector 及其組件的更多資訊可以在 MetaCG 文件中找到。
應用 CGCollector 通常分兩步驟進行。
首先,對專案中的每個原始檔案呼叫cgc
。例如:
for f in $(find ./src -type f ( -iname "*.c" -o -iname "*.cpp" ) ); do
cgc --metacg-format-version=2 $f
done
然後使用cgmerge
將步驟 1 中建立的.ipcg
檔案合併為通用檔案。
"null"
2. 如果您的專案包含多個main
函數,請僅合併具有正確main
函數的文件。 echo "null" > $IPCG_FILENAME
find ./src -name "*.ipcg" -exec cgmerge $IPCG_FILENAME $IPCG_FILENAME {} +
最後的圖需要放入callgraph-analyzer的目錄中。由於目前使用PGIS進行CG分析,因此將產生的整個程式檔案複製到PGIS目錄中。目前,PGIS 目錄中的檔案依照item_flavor.mcg
模式命名非常重要。一個專案代表一個目標應用程式。下一節將詳細介紹術語風味和物品。
# Assuming $PIRA holds the top-level PIRA directory
$> cp my-app.mcg $PIRA/extern/install/pgis/bin/item_flavor.mcg
PIRA 配置包含 PIRA 運行自動過程所需的所有資訊。需要在設定檔中指定的各種目錄可以是絕對路徑,也可以是相對於 pira 執行路徑的路徑。路徑可能包含環境變量,例如$HOME
。這些範例取自./test/integration/GameOfLife
中的 GameOfLife 範例。
使用者指定:在其中尋找後續定義的項目的目錄,在範例中,該目錄是./gol/serial_non_template
。這些目錄被賦予別名,使用“%”符號取消引用。 PIRA 中的項目是目標應用程序,以特定方式構建,這就是它被分組在builds下的配置中的原因。
{
"builds": {
"%gol": {
"items": {
"gol": {
...
}
}
}
}
"directories": {
"gol": "./gol/serial_non_template"
}
}
每個項目都指定應使用哪一台分析儀。預設分析器隨 PIRA 一起提供,原始程式碼可以分別在./extern/src/metacg/pgis
或安裝在./extern/install/pgis/bin
中找到。分析器負責指導儀器的改進,因此是 PIRA 框架的重要組成部分。
argmap欄位指定執行效能實驗時傳遞給目標應用程式的不同參數。如何將參數傳遞到目標應用程式由不同的映射器定義。在範例中,使用了線性映射器,它只是按照列表中給定的順序迭代名為size的參數的值。
"argmap": {
"mapper": "Linear",
"size": [50, 80, 110, 150, 300, 500]
}
立方體欄位是 PIRA 應儲存獲得的 Score-P 設定檔的位置。它將在該位置建立目錄樹,因此使用者可以在 PIRA 完成後,透過簡單地向 Extra-P 建模工具傳遞相應的位置(即範例中的/tmp/pira)來輕鬆呼叫Extra-P 建模工具。
"cubes": "/tmp/pira"
風味字段增加了另一個可能的區別級別,因為目標應用可以以不同的風味構建。一個範例是指定目標應用程式應連結的不同數學庫。
最後, functors目錄將 PIRA 指向尋找使用者提供的 Python 函數的位置,這些函數最終告訴 PIRA 如何建立、運行和分析目標應用程式。在範例中,PIRA 指向相對於配置位置的名為functors的目錄。
"flavors": [
"ct"
],
"functors": "./functors",
"mode": "CT"
在此版本的 PIRA 中,模式欄位被忽略。
到目前為止,使用者需要實作五個不同的函子:
analyze_<ITEM>_<FLAVOR>.py
:呼叫分析器。clean_<ITEM>_<FLAVOR>.py
:清理建置目錄。<ITEM>_<FLAVOR>.py
:建構檢測版本。no_instr_<ITEM>_<FLAVOR>.py
:建構普通版本。runner_<ITEM>_<FLAVOR>.py
:執行目標應用程式。函子通常支援兩種呼叫模式:主動和被動。函子透過將函數get_method()
傳回的字典中的對應值設為True
來告訴 PIRA 它使用哪種模式。
在主動模式下,仿函數本身會呼叫所需的命令,例如建置軟體。呼叫時,函子會傳遞一個**kwargs
參數,其中包含目前目錄和子程序 shell 的實例等。
被動模式僅傳回要執行的命令,例如字串make
來呼叫專案頂級目錄中的簡單 Makefile。它還傳遞一個kwargs
參數,該參數保存特定訊息,例如添加到 CXXFLAGS 或其他連結器標誌所需的預定義值。被動函子的範例可以在examples
和test
目錄中找到。目前,所有實作的函子都使用被動模式。
PIRA 將下列關鍵字參數傳遞給所有函子。此外,不同的 PIRA 元件可能會傳遞額外的參數。
重要提示:我們現在推出自己的 Score-P 版本。因此,不再需要調整 PIRA 中的編譯命令。查看test/integration/AMG2013
中的函子,以了解不同資訊的用法範例。
目前,沒有訊息傳遞給所有函子
[0]
存取第一個參數, [1]
存取第二個參數,依此類推。.so
檔案的路徑(對於 MPI 過濾至關重要)。 某些分析模式需要附加參數。具體來說,PIRA LIDe(見下文)和 Extra-P 建模分析需要使用者提供參數。建立一個 JSON 檔案並使用--analysis-parameters
-switch 提供其到 PIRA 的路徑。以下範例包含 Extra-P 建模模式的參數。聚合多個 Extra-P 模型(當在不同上下文中呼叫函數時)的可用策略有: FirstModel
、 Sum
、 Average
、 Maximum
。
{
"Modeling": {
"extrapolationThreshold": 2.1,
"statementThreshold": 200,
"modelAggregationStrategy": "Sum"
}
}
有關負載不平衡檢測功能的更多詳細信息,請參閱[PI21]。使用--load-imbalance-detection
參數為 PIRA 呼叫提供設定檔的路徑。該 JSON 檔案需要具有以下結構:
{
"metricType": "ImbalancePercentage",
"imbalanceThreshold": 0.05,
"relevanceThreshold": 0.05,
"contextStrategy": "None",
"contextStepCount": 5,
"childRelevanceStrategy": "RelativeToMain",
"childConstantThreshold": 1,
"childFraction": 0.001
}
若要使用 SLURM 工作負載管理器在叢集上執行 PIRA,請使用--slurm-config
標誌呼叫它。給出批次系統設定檔的路徑。請參閱以_Slurm
為後綴的整合測試 ( test/integration/*_Slurm/
)。 PIRA 目前支援具有 SLURM 工作負載管理器的批次系統。 PIRA 支援使用module
系統,該系統可以在 slurm 叢集上找到。
批次系統設定檔是一個JSON文件,其架構如下:
{
"general": {
"backend": "slurm",
"interface": "pyslurm",
"timings": "subprocess"
},
"module-loads": [
{
"name": "gcc",
"version": "8.5"
},
{
"name": "llvm",
"version": "10.0.0",
"depends-on": [
{
"name": "gcc",
"version": "8.5"
}
]
}
],
"batch-settings": {
"time_str": "00:10:00",
"mem_per_cpu": 3800,
"number_of_tasks": 1,
"partition": null,
"reservation": null,
"account": "your_account_here",
"cpus_per_task": 96
}
}
分解:
general
部分:允許您選擇 PIRA 在批次系統上執行程式碼的方式。由於本節中的每個選項都是可選的,因此如果您願意使用預設值,則可以省略整個部分:backend
:使用什麼工作負載管理器。選擇: slurm
,用於 slurm 工作負載管理器。預設值: slurm
,因此可選。interface
:PIRA 應以何種方式與批次系統管理員互動。對於 SLURM 後端,這些是: pyslurm
,使用 PySlurm (這需要安裝 PySlurm,請參閱本節; sbatch-wait
,使用帶有--wait
標誌的標準sbatch
; os
,用於標準sbatch
和squeue
交互調用。預設值: pyslurm
,因此可選。timings
:目標程式碼的計時應該如何完成。選擇: subprocess
,用於在子進程中使用 python 包裝器和os.times
進行計時(如果在本地運行,則與 PIRA 的做法完全相同); os
,使用/usr/bin/time
。預設值: subprocess
,因此可選。force-sequential
:預設false
。設定為true
以強制 PIRA/批次系統依序執行所有運行(一次僅執行一次目標程式碼)。這表示 PIRA 將注意您的批次系統運行重複,以及按順序擴展實驗中的不同作業。如果設定為false
保留為 false,PIRA 將嘗試指示批次系統在每次迭代中並行執行盡可能多的執行。module-loads
部分:目前未在 PIRA 中使用,正在進行中!目前,您需要在啟動 PIRA 之前手動加載所有模組!意味著哪些模組應該與module
系統一起載入。這需要一個到位(PIRA 可能使用命令module load
和module purge
)。如果您沒有適當的module
系統,或不想使用它,請完全忽略此部分,或設定"module-loads": null
。若要指定 PIRA 應載入的模組,請指定模組列表,如上例所示。name
。version
是可選的,如果沒有給出,它將取決於module
系統加載的預設模組版本。建議始終明確給出版本。depends-on
也是可選的。給出該模組所依賴的模組列表。這些模組必須有一個name
,並且可以選擇指定version
。 PIRA 使用此處定義的依賴項來確定模組的載入順序null
,則假定該模組沒有依賴項。depends-on
PIRA 將(嘗試)完全按照設定檔中給出的順序載入模組。batch-setting
部分:批次系統的實際硬體和作業選項。該部分中的某些選項是強制性的,您不能省略該部分。time
: sbatch --time
選項,強制。mem-per-cpu
: sbatch --mem-per-cpu
選項,強制。ntasks
: sbatch --ntasks
選項,強制。partition
、 reservation
、 account
(全部預設為null
=未給定)、 cpus-per-task
(預設為4
)、 exclusive
(預設為true
; pyslurm
不支援)和cpu-freq
(預設為null
)。sbatch
選項。這是由於 PIRA 內部使用了一些選項(例如--array
選項)來將重複對應到作業陣列。 如何在叢集上安裝 PySlurm 以及安裝哪個版本,很大程度上取決於您的 SLURM 版本和 SLURM 安裝。 pyslurm 與 PIRA 的安裝和打包解決方案正在進行中。請參閱他們的自述文件。您可以嘗試以下一些方法:
include
和lib
目錄。python3 setup.py build --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
python3 setup.py install --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
。