一、什麼是Python Wall Time和CPU Time
Python中,“Wall Time”和“CPU Time”是衡量程序執行時間和資源消耗的兩個指標。Wall Time反映的是實際流逝的時間,即程序開始執行到執行完成所經過的時間;而CPU Time則反映的是程序單獨佔用CPU的時間,不包括等待輸入輸出和其他外部因素所耗費的時間。
下面是一個簡單的代碼示例來說明它們的區別:
import time # 測試程序:計算0~999999的和 start_time = time.time() s = 0 for i in range(1000000): s += i end_time = time.time() print("Wall Time:", end_time - start_time) start_cpu = time.process_time() s = 0 for i in range(1000000): s += i end_cpu = time.process_time() print("CPU Time:", end_cpu - start_cpu)
當我們運行上面這段程序時,輸出結果可能類似於:
Wall Time: 0.123456 CPU Time: 0.038461
可以看到,Wall Time和CPU Time的數值差別很大,這是因為Python程序在執行過程中經常會因為等待輸入輸出、等待其他任務完成等原因而暫停運行,導致Wall Time比CPU Time長。
二、如何計算多個函數的Wall Time和CPU Time
當我們需要比較不同的函數在程序中的執行時間和資源消耗時,我們可以使用Python內置的裝飾器來計算它們的Wall Time和CPU Time。
首先,我們定義一個裝飾器函數來計算函數的Wall Time:
import time def calculate_wall_time(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(func.__name__, "Wall Time:", end_time - start_time) return result return wrapper
定義好裝飾器函數後,我們在需要計算Wall Time的函數前加上@calculate_wall_time修飾符即可:
@calculate_wall_time def func_1(): ...
類似地,我們可以定義另一個裝飾器函數來計算函數的CPU Time:
import time def calculate_cpu_time(func): def wrapper(*args, **kwargs): start_cpu = time.process_time() result = func(*args, **kwargs) end_cpu = time.process_time() print(func.__name__, "CPU Time:", end_cpu - start_cpu) return result return wrapper
使用方法同上:
@calculate_cpu_time def func_2(): ...
通過使用裝飾器函數,我們可以方便地計算多個函數的Wall Time和CPU Time,並進行比較。
三、如何使用profiler分析程序的性能問題
在比較重要的程序中,我們需要進行更深入的分析才能確定性能瓶頸出現在哪裡。Python的內置模塊profiler可以幫助我們分析程序的性能問題。
例如,我們定義一個複雜的函數來計算斐波那契數列的第n項:
import time def fib(n): if n <= 1: return n else: return fib(n-1) + fib(n-2)
如果我們需要計算fib(35)時的Wall Time和CPU Time,我們可以使用之前的裝飾器函數來計算:
@calculate_wall_time def test_wall_time(): fib(35) @calculate_cpu_time def test_cpu_time(): fib(35) test_wall_time() test_cpu_time()
運行結果可能類似於:
test_wall_time Wall Time: 3.524221181869507 test_cpu_time CPU Time: 3.51171875
可以看到,fib(35)的Wall Time和CPU Time都比較長。使用Python內置模塊cProfile可以查看這個函數每一行的運行情況和耗費的時間:
import cProfile cProfile.run('fib(35)')
運行結果可能類似於:
結果輸出太長,省略...
在輸出結果中,每一行都顯示了這個函數在運行中的執行時間和調用次數,我們可以從中找出哪些是時間最長的部分,從而確定可能的性能瓶頸和優化方向。
四、如何優化程序的性能問題
當我們確定了程序的性能瓶頸後,就可以考慮優化程序來提高執行效率。
一些常見的優化方法有:
- 使用局部變量和常量代替全局變量和動態類型
- 使用Python內置函數和模塊代替自定義函數和算法
- 使用生成器和迭代器代替列表解析和循環結構
- 使用線程和進程來利用多核CPU
例如,我們可以修改之前的斐波那契數列函數fib(n)來使用局部變量和迭代器進行優化:
def fib(n): a, b = 0, 1 for i in range(n): a, b = b, a + b return a
使用優化後的函數來計算fib(1000000)的Wall Time和CPU Time:
@calculate_wall_time def test_wall_time(): fib(1000000) @calculate_cpu_time def test_cpu_time(): fib(1000000) test_wall_time() test_cpu_time()
運行結果可能類似於:
test_wall_time Wall Time: 0.28377318382263184 test_cpu_time CPU Time: 0.28125
可以看到,使用優化後的函數計算fib(1000000)的Wall Time和CPU Time都大幅度優化了。
總結
在Python中,我們可以使用Wall Time和CPU Time來衡量程序執行時間和資源消耗,並使用內置模塊profiler來分析程序的性能問題,並使用局部變量、內置函數、迭代器等技巧來優化程序的性能。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/243450.html