[英]Why are Python operations 30× slower after calling time.sleep or subprocess.Popen?
考慮以下循環:
for i in range(20):
if i == 10:
subprocess.Popen(["echo"]) # command 1
t_start = time.time()
1+1 # command 2
t_stop = time.time()
print(t_stop - t_start)
當“命令 1”在它之前運行時,“命令 2”命令需要系統地更長的時間來運行。 下圖顯示了1+1
的執行時間作為循環索引i
的函數,平均超過 100 次運行。
的執行1+1
是慢30倍之前時subprocess.Popen
。
它變得更加奇怪。 有人可能認為只有在subprocess.Popen()
之后運行的第一個命令會受到影響,但事實並非如此。 以下循環顯示當前循環迭代中的所有命令都受到影響。 但隨后的循環迭代似乎基本沒問題。
var = 0
for i in range(20):
if i == 10:
# command 1
subprocess.Popen(['echo'])
# command 2a
t_start = time.time()
1 + 1
t_stop = time.time()
print(t_stop - t_start)
# command 2b
t_start = time.time()
print(1)
t_stop = time.time()
print(t_stop - t_start)
# command 2c
t_start = time.time()
var += 1
t_stop = time.time()
print(t_stop - t_start)
這是此循環的執行時間圖,平均超過 100 次運行:
更多備注:
subprocess.Popen()
與(“命令1”) time.sleep()
或rawkit的libraw C ++綁定初始化( libraw.bindings.LibRaw()
但是,使用其他帶有 C++ 綁定的庫,例如libraw.py或 OpenCV 的cv2.warpAffine()
不會影響執行時間。 打開文件也不行。time.time()
引起的,因為它是可見的timeit.timeit()
,甚至在print()
結果出現時手動測量。subprocess.Popen
)和“命令 2”之間執行了許多不同的(可能是 CPU 和內存消耗的)操作時,也會發生這種情況。arr += 1
操作可能需要長達 300 毫秒!問題:什么可能導致這種效果,為什么它只影響當前循環迭代?
我懷疑它可能與上下文切換有關,但這似乎並不能解釋為什么整個循環迭代會受到影響。 如果上下文切換確實是原因,為什么有些命令會觸發它而其他命令則不會?
我的猜測是,這是由於 Python 代碼從 CPU/內存系統中的各種緩存中被逐出
perflib
包可用於提取有關緩存狀態的更詳細的 CPU 級別統計信息 — 即命中/未命中數。
在LIBPERF_COUNT_HW_CACHE_MISSES
Popen()
調用后,我得到了大約 5 倍的LIBPERF_COUNT_HW_CACHE_MISSES
計數器:
from subprocess import Popen, DEVNULL
from perflib import PerfCounter
import numpy as np
arr = []
p = PerfCounter('LIBPERF_COUNT_HW_CACHE_MISSES')
for i in range(100):
ti = []
p.reset()
p.start()
ti.extend(p.getval() for _ in range(7))
Popen(['echo'], stdout=DEVNULL)
ti.extend(p.getval() for _ in range(7))
p.stop()
arr.append(ti)
np.diff(np.array(arr), axis=1).mean(axis=0).astype(int).tolist()
給我:
2605, 2185, 2127, 2099, 2407, 2120,
5481210,
16499, 10694, 10398, 10301, 10206, 10166
(在非標准地方打斷的線條表示代碼流程)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.