• 文件 >
  • 基準測試工具 - torch.utils.benchmark
捷徑

基準測試工具 - torch.utils.benchmark

class torch.utils.benchmark.Timer(stmt='pass', setup='pass', global_setup='', timer=<built-in function perf_counter>, globals=None, label=None, sub_label=None, description=None, env=None, num_threads=1, language=Language.PYTHON)[原始碼]

用於測量 PyTorch 語句執行時間的輔助類別。

如需有關如何使用此類別的完整教學,請參閱:https://pytorch.com.tw/tutorials/recipes/recipes/benchmark.html

PyTorch Timer 是基於 timeit.Timer(實際上在內部使用 timeit.Timer),但有幾個主要差異

  1. 執行時期感知

    Timer 將執行預熱(這很重要,因為 PyTorch 的某些元素是延遲初始化的),設定執行緒池大小,以便比較是公平的,並在必要時同步非同步 CUDA 函數。

  2. 專注於重複

    在測量程式碼時,尤其是複雜的內核/模型,執行間的差異是一個顯著的混淆因素。預期所有測量都應包含重複,以量化雜訊並允許計算中位數,這比平均值更穩健。為此,此類別偏離了 timeit API,在概念上合併了 timeit.Timer.repeattimeit.Timer.autorange。(確切的演算法在方法文件字串中討論。)在不需要自適應策略的情況下,會複製 timeit 方法。

  3. 可選的中繼資料

    在定義 Timer 時,可以選擇指定 labelsub_labeldescriptionenv。(稍後定義)這些欄位包含在結果物件的表示中,並由 Compare 類別用於分組和顯示結果以進行比較。

  4. 指令計數

    除了實際時間之外,Timer 還可以在 Callgrind 下執行語句並報告執行的指令。

timeit.Timer 建構函數參數直接類似

stmtsetuptimerglobals

PyTorch Timer 特定的建構函數參數

labelsub_labeldescriptionenvnum_threads

參數
  • stmt (str) – 要在迴圈中執行並計時的程式碼片段。

  • setup (str) – 可選的設定程式碼。用於定義在 stmt 中使用的變數

  • global_setup (str) – (僅限 C++)放置在檔案頂層的程式碼,用於 #include 語句等。

  • timer (Callable[[], float]) – 傳回當前時間的可呼叫物件。如果 PyTorch 是在沒有 CUDA 的情況下建置的,或者沒有 GPU,則預設為 timeit.default_timer;否則,它將在測量時間之前同步 CUDA。

  • globals (Optional[Dict[str, Any]]) – 一個字典,定義了執行 stmt 時的全局變數。這是提供 stmt 所需變數的另一種方法。

  • label (Optional[str]) – 總結 stmt 的字串。例如,如果 stmt 是“torch.nn.functional.relu(torch.add(x, 1, out=out))”,則可以將 label 設定為“ReLU(x + 1)”以提高可讀性。

  • sub_label (Optional[str]) –

    提供補充資訊以消除具有相同 stmt 或 label 的測量的歧義。例如,在我們上面的範例中,sub_label 可能是“float”或“int”,因此很容易區分:在使用 Compare 列印測量值或摘要時,“ReLU(x + 1):(float)”

    “ReLU(x + 1):(int)”。

  • description (Optional[str]) –

    用於區分具有相同標籤和子標籤的測量的字串。 description 的主要用途是向 Compare 發出數據列的信號。 例如,可以使用 Compare 根據輸入大小設置它以創建以下形式的表格

                            | n=1 | n=4 | ...
                            ------------- ...
    ReLU(x + 1): (float)    | ... | ... | ...
    ReLU(x + 1): (int)      | ... | ... | ...
    

    它也會在打印 Measurement 時包含在內。

  • env (Optional[str]) – 此標籤表示在不同環境中運行但相同的任務,因此並不相同,例如在對內核進行 A/B 測試時。 合併重複運行時,Compare 會將具有不同 env 規範的 Measurement 視為不同的測量。

  • num_threads (int) – 執行 stmt 時 PyTorch 線程池的大小。 單線程性能非常重要,因為它既是關鍵的推理工作負載,也是內在算法效率的良好指標,因此默認設置為 1。 這與嘗試利用所有內核的默認 PyTorch 線程池大小形成對比。

adaptive_autorange(threshold=0.1, *, min_run_time=0.01, max_run_time=10.0, callback=None)[source]

blocked_autorange 類似,但也會檢查測量值的可變性並重複執行,直到 iqr/median 小於 threshold 或達到 max_run_time

在較高的層級上,adaptive_autorange 會執行以下虛擬程式碼

`setup`

times = []
while times.sum < max_run_time
    start = timer()
    for _ in range(block_size):
        `stmt`
    times.append(timer() - start)

    enough_data = len(times)>3 and times.sum > min_run_time
    small_iqr=times.iqr/times.mean<threshold

    if enough_data and small_iqr:
        break
參數
  • threshold (float) – iqr/median 閾值的值,用於停止

  • min_run_time (float) – 檢查 threshold 之前所需的總運行時間

  • max_run_time (float) – 所有測量的總運行時間,與 threshold 無關

回傳

一個 Measurement 物件,其中包含測量的運行時間和重複次數,可用於計算統計數據。 (平均值、中位數等)

回傳型別

Measurement

blocked_autorange(callback=None, min_run_time=0.2)[source]

測量許多重複樣本,同時將計時器開銷降至最低。

在較高的層級上,blocked_autorange 會執行以下虛擬程式碼

`setup`

total_time = 0
while total_time < min_run_time
    start = timer()
    for _ in range(block_size):
        `stmt`
    total_time += (timer() - start)

請注意內部迴圈中的變數 block_size。區塊大小的選擇對測量質量非常重要,並且必須平衡兩個相互競爭的目標

  1. 較小的區塊大小會導致更多重複樣本和通常更好的統計數據。

  2. 較大的區塊大小可以更好地攤銷 timer 調用的成本,並產生偏差較小的測量結果。 這一點很重要,因為 CUDA 同步時間並非微不足道(大約為個位數到十幾微秒),否則會導致測量結果產生偏差。

blocked_autorange 通過運行預熱期來設置 block_size,增加區塊大小,直到計時器開銷小於總計算量的 0.1%。 然後,將此值用於主測量迴圈。

回傳

一個 Measurement 物件,其中包含測量的運行時間和重複次數,可用於計算統計數據。 (平均值、中位數等)

回傳型別

Measurement

collect_callgrind(number: int, *, repeats: None, collect_baseline: bool, retain_out_file: bool) CallgrindStats[source]
collect_callgrind(number: int, *, repeats: int, collect_baseline: bool, retain_out_file: bool) Tuple[CallgrindStats, ...]

使用 Callgrind 收集指令計數。

與掛鐘時間不同,指令計數是確定性的(取決於程序本身的非確定性和 Python 解釋器產生的少量抖動)。 這使得它們非常適合進行詳細的性能分析。 此方法會在單獨的進程中運行 stmt,以便 Valgrind 可以檢測程序。 由於檢測,性能會嚴重下降,但由於少量迭代通常足以獲得良好的測量結果,因此可以改善這種情況。

為了使用此方法,必須安裝 valgrindcallgrind_controlcallgrind_annotate

因為調用方(此進程)和 stmt 執行之間存在進程邊界,所以 globals 不能包含任意的內存數據結構。 (與計時方法不同)相反,全局變數僅限於內建函數、nn.Modules 和 TorchScripted 函數/模組,以減少序列化和後續反序列化產生的意外因素。 GlobalsBridge 類別提供了有關此主題的更多詳細信息。 請特別注意 nn.Modules:它們依賴於 pickle,您可能需要將導入添加到 setup 中才能正確傳輸它們。

默認情況下,將收集並緩存空語句的配置文件,以指示有多少指令來自驅動 stmt 的 Python 迴圈。

回傳

一個 CallgrindStats 物件,它提供指令計數和一些用於分析和操作結果的基本工具。

timeit(number=1000000)[source]

反映 timeit.Timer.timeit() 的語義。

執行主語句 (stmt) number 次。 https://docs.python.club.tw/3/library/timeit.html#timeit.Timer.timeit

回傳型別

Measurement

class torch.utils.benchmark.Measurement(number_per_run, raw_times, task_spec, metadata=None)[source]

Timer 測量的結果。

此類別存儲給定語句的一個或多個測量值。 它是可序列化的,並為下游消費者提供多種便利方法(包括詳細的 __repr__)。

static merge(measurements)[source]

合併重複樣本的便利方法。

Merge 會將時間外推至 number_per_run=1,並且不會傳輸任何中繼數據。 (因為它在重複樣本之間可能有所不同)

回傳型別

List[Measurement]

property significant_figures: int

近似有效數字估計。

此屬性旨在提供一種估計測量精度的方法。 它僅使用四分位距來估計統計數據,以嘗試減輕尾部的偏差,並使用靜態 z 值 1.645,因為它預計不會用於 n 的較小值,因此 z 可以近似於 t

有效數字估計與 trim_sigfig 方法結合使用,以提供更易於理解的數據摘要。 __repr__ 不使用此方法; 它只是顯示原始值。 有效數字估計適用於 Compare

class torch.utils.benchmark.CallgrindStats(task_spec, number_per_run, built_with_debug_symbols, baseline_inclusive_stats, baseline_exclusive_stats, stmt_inclusive_stats, stmt_exclusive_stats, stmt_callgrind_out)[source]

Timer 所收集的 Callgrind 結果的頂層容器。

操作通常使用 FunctionCounts 類別完成,該類別可透過呼叫 CallgrindStats.stats(…) 取得。也提供了一些便利的方法;最重要的是 CallgrindStats.as_standardized()

as_standardized()[source]

從函式字串中移除程式庫名稱和一些前綴。

當比較兩組不同的指令計數時,絆腳石可能是路徑前綴。Callgrind 在報告函式時會包含完整檔案路徑(應該如此)。但是,這在比較設定檔時可能會導致問題。如果一個關鍵元件(例如 Python 或 PyTorch)是在兩個設定檔的不同位置建構的,則可能會導致類似以下的情況:

23234231 /tmp/first_build_dir/thing.c:foo(...)
 9823794 /tmp/first_build_dir/thing.c:bar(...)
  ...
   53453 .../aten/src/Aten/...:function_that_actually_changed(...)
  ...
 -9823794 /tmp/second_build_dir/thing.c:bar(...)
-23234231 /tmp/second_build_dir/thing.c:foo(...)

移除前綴可以透過正規化字串並在比較時更好地消除等效呼叫站點來改善此問題。

回傳型別

CallgrindStats

counts(*, denoise=False)[source]

傳回執行的指令總數。

如需 denoise 引數的說明,請參閱 FunctionCounts.denoise()

回傳型別

int

delta(other, inclusive=False)[source]

比較兩組計數的差異。

收集指令計數的一個常見原因是確定特定變更對執行某些工作單元所需的指令數量的影響。如果變更增加了該數字,則下一個邏輯問題是「為什麼」。這通常涉及查看程式碼的哪一部分增加了指令計數。此函式會自動執行該流程,以便可以輕鬆地在包含和排除的基礎上比較計數差異。

回傳型別

FunctionCounts

stats(inclusive=False)[source]

傳回詳細的函式計數。

從概念上講,傳回的 FunctionCounts 可以被視為 (count, path_and_function_name) 元組的元組。

inclusive 與 callgrind 的語義相符。如果為 True,則計數包括由子項執行的指令。inclusive=True 對於識別程式碼中的熱點很有用;inclusive=False 對於在比較兩次不同執行的計數時減少雜訊很有用。(如需更多詳細資訊,請參閱 CallgrindStats.delta(…))

回傳型別

FunctionCounts

class torch.utils.benchmark.FunctionCounts(_data, inclusive, truncate_rows=True, _linewidth=None)[source]

用於操作 Callgrind 結果的容器。

它支援:
  1. 加法和減法以組合或比較結果差異。

  2. 類似元組的索引。

  3. 一個 denoise 函式,用於去除已知是非確定性且相當雜訊的 CPython 呼叫。

  4. 兩種用於自訂操作的高階方法(filtertransform)。

denoise()[source]

移除已知的雜訊指令。

CPython 直譯器中的幾項指令相當雜訊。這些指令涉及 Python 用於對應變數名稱的 unicode 到字典的查詢。FunctionCounts 通常是一個與內容無關的容器,但是這對於取得可靠的結果來說非常重要,因此值得例外。

回傳型別

FunctionCounts

filter(filter_fn)[source]

僅保留將 filter_fn 套用至函式名稱時傳回 True 的元素。

回傳型別

FunctionCounts

transform(map_fn)[source]

map_fn 套用至所有函式名稱。

這可以用於正規化函式名稱(例如,移除檔案路徑中不相關的部分)、透過將多個函式對應到相同名稱來合併項目(在這種情況下,計數會加總在一起)等等。

回傳型別

FunctionCounts

class torch.utils.benchmark.Compare(results)[source]

用於在格式化表格中顯示多項測量結果的輔助類別。

表格格式基於 torch.utils.benchmark.Timer 中提供的資訊欄位(descriptionlabelsub_labelnum_threads 等)。

可以使用 print() 直接列印表格,或將其轉換為 str

如需有關如何使用此類別的完整教學,請參閱:https://pytorch.com.tw/tutorials/recipes/recipes/benchmark.html

參數

results (List[Measurement]) – 要顯示的測量結果清單。

colorize(rowwise=False)[source]

為格式化表格著色。

預設情況下按欄著色。

extend_results(results)[source]

將結果附加到已儲存的結果。

所有添加的結果都必須是 Measurement 的實例。

highlight_warnings()[source]

在建構格式化表格時啟用警告醒目提示。

print()[source]

列印格式化表格

trim_significant_figures()[source]

在建構格式化表格時啟用有效數字的修剪。

文件

取得 PyTorch 的完整開發人員文件

查看文件

教學課程

取得適用於初學者和進階開發人員的深入教學課程

查看教學課程

資源

尋找開發資源並取得問題的解答

查看資源