在 Python 數據科學領域,pandas 長期以來一直是直觀數據操作和分析的首選庫。但是,隨著數據量的增長,CPU 受限的 pandas 工作流可能會成為瓶頸。
這就是 cuDF 及其 pandas 加速器模式 cudf.pandas
的用武之地。此模式可盡可能使用 GPU 加速操作,并無縫回退至 CPU 以執行不受支持的操作。此方法的基本支柱是 cudf.pandas
分析器,該分析器可用于了解與 CPU 相比,GPU 上執行的代碼量。
在本文中,我們將討論 cudf.pandas
分析器是什么,如何使用它,以及為什么它對于理解和優化加速 pandas 工作負載至關重要。
cudf.pandas 分析器概述?
Jupyter 和 IPython 中提供的 cudf.pandas.profile
magic 命令是一種分析工具,可實時分析 pandas 式代碼。啟用 cudf.pandas
擴展后,分析器將報告每個操作的執行設備 (GPU 或 CPU),并統計特定函數或方法的觸發次數。
通過捕獲這些數據,您可以快速確定以下內容:
- 哪些操作在 GPU 上完全加速。
- 哪些操作返回到 CPU 上的 pandas。
- 潛在瓶頸或不必要的數據傳輸可能潛伏在何處。
啟用分析器?
首先,在 Notebook 中加載 cudf.pandas
擴展程序,就像加載其他 IPython 魔術一樣:
% load_ext cudf.pandas import pandas as pd |
從這里開始,您可以開始編寫 pandas 代碼,例如讀取 CSV、合并 DataFrames 或運行 groupbys,并讓 cudf.pandas
自動決定如何在 GPU 上加速這些代碼,或者在需要時使用 CPU。
分析的實際應用?
使用 cudf.pandas
分析器的方法有以下幾種:
- 使用單元級分析器
- 使用線條分析器
- 使用命令行中的 profiler
使用單元級分析器?
在 Jupyter 或 IPython 中,您可以逐單元激活分析:
% % cudf.pandas.profile df = pd.DataFrame({ 'a' : [ 0 , 1 , 2 ], 'b' : [ 3 , 4 , 3 ]}) df. min (axis = 1 ) out = df.groupby( 'a' ). filter ( lambda group: len (group) > 1 ) |
單元完成后,您將看到一個輸出,其中分解了與 CPU 相比在 GPU 上運行的操作、每個操作的調用次數,以及用于發現性能瓶頸的便捷摘要。
Total time elapsed: 0.256 seconds 3 GPU function calls in 0.170 seconds 1 CPU function calls in 0.009 seconds Stats ┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ ┃ Function ┃ GPU ncalls ┃ GPU cumtime ┃ GPU percall ┃ CPU ncalls ┃ CPU cumtime ┃ CPU percall ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ │ DataFrame │ 1 │ 0.031 │ 0.031 │ 0 │ 0.000 │ 0.000 │ │ DataFrame.min │ 1 │ 0.137 │ 0.137 │ 0 │ 0.000 │ 0.000 │ │ DataFrame.groupby │ 1 │ 0.001 │ 0.001 │ 0 │ 0.000 │ 0.000 │ │ DataFrameGroupBy.filter │ 0 │ 0.000 │ 0.000 │ 1 │ 0.009 │ 0.009 │ └─────────────────────────┴────────────┴─────────────┴─────────────┴────────────┴─────────────┴─────────────┘ Not all pandas operations ran on the GPU. The following functions required CPU fallback: - DataFrameGroupBy.filter To request GPU support for any of these functions, please file a Github issue here: https: //github .com /rapidsai/cudf/issues/new/choose . |
DataFrameGroupBy.filter
未在 GPU 上加速,因此您可以看到表中的一次 CPU 調用需要 0.025 秒。
使用線條分析器?
要更深入地了解單元中每一行的執行情況,請運行以下代碼示例:
% % cudf.pandas.line_profile df = pd.DataFrame({ 'a' : [ 0 , 1 , 2 ], 'b' : [ 3 , 4 , 3 ]}) df. min (axis = 1 ) out = df.groupby( 'a' ). filter ( lambda group: len (group) > 1 ) |
在這里,profiler 逐行顯示執行細節,以便更輕松地發現導致 CPU 回退或性能降低的特定代碼行。
Total time elapsed: 0.244 seconds Stats ┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ ┃ Line no. ┃ Line ┃ GPU TIME(s) ┃ CPU TIME(s) ┃ ┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ │ 2 │ df = pd.DataFrame({'a': [0, 1, 2], 'b': [3, 4, 3]}) │ 0.004833249 │ │ │ │ │ │ │ │ 3 │ df.min(axis=1) │ 0.006497159 │ │ │ │ │ │ │ │ 4 │ out = df.groupby('a').filter(lambda group: len(group) > 1) │ 0.000599624 │ 0.000347643 │ │ │ │ │ │ └──────────┴────────────────────────────────────────────────────────────────┴─────────────┴─────────────┘ |
使用命令行中的 profiler
您還可以通過傳遞 --profile
參數從命令行運行 cudf.pandas
分析器。
以下是 demo.py
的內容:
import pandas as pd s = pd.Series([ 1 , 2 , 3 ]) s = (s * 10 ) + 2 print (s) |
運行以下命令:
python - m cudf.pandas – - profile demo.py |
您將看到 profile stats 輸出:
Total time elapsed: 0.852 seconds 4 GPU function calls in 0.029 seconds 0 CPU function calls in 0.000 seconds Stats ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓ ┃ Function ┃ GPU ncalls ┃ GPU cumtime ┃ GPU percall ┃ CPU ncalls ┃ CPU cumtime ┃ CPU percall ┃ ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩ │ Series │ 1 │ 0.002 │ 0.002 │ 0 │ 0.000 │ 0.000 │ │ OpsMixin.__mul__ │ 1 │ 0.011 │ 0.011 │ 0 │ 0.000 │ 0.000 │ │ OpsMixin.__add__ │ 1 │ 0.008 │ 0.008 │ 0 │ 0.000 │ 0.000 │ │ object.__str__ │ 1 │ 0.008 │ 0.008 │ 0 │ 0.000 │ 0.000 │ └──────────────────┴────────────┴─────────────┴─────────────┴────────────┴─────────────┴─────────────┘ |
分析為何重要?
在 GPU 加速方面,并非所有功能都能自動獲得支持。某些操作 (例如某些尚未在 GPU 上實現的 Python 級函數、自定義 lambdas 或 DataFrame 方法) 可能會觸發 CPU 回退。
分析器可幫助您精確查看這些回退的出現位置。借助這些知識,您可以調整工作流程、重寫某些函數,或調查需要改進的潛在領域:
- 重寫受 CPU 限制的運算: 某些用戶定義的函數或運算可能會進行修改,使其對 GPU 更加友好。
- 留意頻繁的數據傳輸 :CPU 和 GPU 之間的過多數據傳輸可能會抵消加速所帶來的收益。識別這些對更大限度地提高速度至關重要,因為重復的 GPU 操作序列和 CPU 操作通常會導致昂貴的數據傳輸。
- 及時了解最新動態:cuDF 不斷添加功能 (并彌合與 pandas 之間的差距)。
了解哪些方法目前受 CPU 限制,有助于您跟蹤未來的改進。
結束語?
pandas 用戶體驗是現代數據科學的核心,但擴展到大型數據集通常會對 CPU 性能造成壓力。
借助 cudf.pandas
,您可以盡可能使用 GPU 的速度獲得相同的直觀 API,并為不受支持的操作提供自動 CPU 回退。cudf.pandas
分析器是了解此混合 CPU/GPU 生態系統的關鍵,可突出顯示加速機會,并幫助您優化代碼以實現最佳性能。
在您的數據項目中嘗試一下。通過分析代碼并識別 CPU 回退,您可以快速突破 pandas 的極限,而無需離開其熟悉的 API 的舒適性。
如果您遇到希望通過 GPU 加速的 API,請在 /rapidsai/cudf GitHub 存儲庫中 打開 GitHub 問題 。
?