網(wǎng)站首頁 編程語言 正文
前言
最近在解決一些算法優(yōu)化的問題,為了實時性要求,必須精益求精的將資源利用率用到極致。同時對算法中一些處理進行多線程或者多進程處理。
在對代碼的調(diào)試過程中,發(fā)現(xiàn)在進程間隊列使用耗時很長,特別是圖片這種比較大的數(shù)據(jù)的時候。
可以先看一下我下面的demo是不是符合你的場景。
下面還有我的解決方案。
使用進程間Queue效率問題場景
代碼樣例如下,模擬從兩個視頻讀取圖片幀進行處理。
#!/user/bin/env python
# coding=utf-8
"""
@project : csdn-pro
@author : 劍客阿良_ALiang
@file : test13.py
@ide : PyCharm
@time : 2022-09-13 10:47:35
"""
import time
import cv2
from multiprocessing import Queue, Process
def fun1(q: Queue):
cap = cv2.VideoCapture("11.mp4")
a = []
while cap.isOpened():
ret, frame = cap.read()
if ret:
a.append(frame)
if len(a) == 25:
q.put(a)
a = []
time.sleep(0.038)
def fun2(q: Queue):
cap = cv2.VideoCapture("3333333.mp4")
a = []
while cap.isOpened():
ret, frame = cap.read()
if ret:
a.append(frame)
if len(a) == 25:
q.put(a)
a = []
time.sleep(0.038)
def fun3(q1: Queue, q2: Queue, q3: Queue):
while True:
st0 = time.time()
a1 = q1.get()
st1 = time.time()
a2 = q2.get()
st2 = time.time()
print("{} 耗時:{} - {}".format(time.time(), st1 - st0, st2 - st1))
q3.put((a1, a2))
def fun4(q3: Queue):
while True:
st0 = time.time()
a1, a2 = q3.get()
et = time.time()
print("hhhh耗時: {}".format(et - st0))
if __name__ == '__main__':
q1 = Queue()
q2 = Queue()
q3 = Queue()
p1 = Process(target=fun1, args=(q1,))
p2 = Process(target=fun2, args=(q2,))
p3 = Process(target=fun3, args=(q1, q2, q3,))
p4 = Process(target=fun4, args=(q3,))
p1.start()
p2.start()
p3.start()
p4.start()
p1.join()
p2.join()
p3.join()
p4.join()
代碼說明:
1、上面模擬每秒25幀讀取圖片,并傳遞一個25幀的圖片list給到隊列。
我們看一下從queue獲取圖片list的效率。部分執(zhí)行結(jié)果如下。
1663139091.3648114 耗時:1.6036181449890137 - 0.1361703872680664
hhhh耗時: 3.0635826587677
1663139093.056612 耗時:1.5302414894104004 - 0.1615591049194336
hhhh耗時: 1.6867034435272217
1663139094.7388775 耗時:1.5256507396697998 - 0.1566147804260254
hhhh耗時: 1.6849782466888428
1663139096.36547 耗時:1.4680161476135254 - 0.15857625007629395
hhhh耗時: 1.651228427886963
1663139097.9867501 耗時:1.4417593479156494 - 0.179520845413208
hhhh耗時: 1.609663963317871
1663139099.5894623 耗時:1.4391484260559082 - 0.16356372833251953
hhhh耗時: 1.7086796760559082
1663139101.3031366 耗時:1.5481102466583252 - 0.16556406021118164
hhhh耗時: 1.657604455947876
1663139102.9448056 耗時:1.470097303390503 - 0.1715717315673828
hhhh耗時: 1.5316739082336426
1663139104.5233243 耗時:1.4139580726623535 - 0.16456055641174316
Process finished with exit code -1
可以看出我們從進程隊列g(shù)et數(shù)據(jù)的耗時很長,從q3中同時獲取的時間如藍色標記,遠大于1秒鐘。
而整體獲取圖片幀的效率如紅色標記,間隔時間大于1秒。
采用管道模式解決
這個時間間隔沒法接受,我才用multiprocessing.Pipe管道來提前輸入圖片。
樣例代碼如下:
#!/user/bin/env python
# coding=utf-8
"""
@project : csdn-pro
@author : 劍客阿良_ALiang
@file : test13.py
@ide : PyCharm
@time : 2022-09-13 10:47:35
"""
import threading
import time
import cv2
from multiprocessing import Queue, Process, Pipe
def fun1(pipe_in):
cap = cv2.VideoCapture("11.mp4")
while cap.isOpened():
ret, frame = cap.read()
if ret:
ret, frame = cap.read()
pipe_in.send((int(time.time()), frame))
time.sleep(0.038)
def fun2(pipe_in):
cap = cv2.VideoCapture("3333333.mp4")
while cap.isOpened():
ret, frame = cap.read()
if ret:
ret, frame = cap.read()
pipe_in.send((int(time.time()), frame))
time.sleep(0.038)
def fun3(pipe_rev1, pipe_rev2):
def handle(pipe_rev1, q1):
_cul = 0
a = []
while True:
_t, _frame = pipe_rev1.recv()
if _cul == 0:
a.append(_frame)
_cul = _t
elif _t > _cul != 0:
if len(a) != 0:
q1.put(a)
_cul = _t
a = []
a.append(_frame)
elif _t == _cul != 0:
a.append(_frame)
q1 = Queue()
q2 = Queue()
threading.Thread(target=handle, args=(pipe_rev1, q1,)).start()
threading.Thread(target=handle, args=(pipe_rev2, q2,)).start()
while True:
if not q1.empty() and not q2.empty():
st0 = time.time()
_f1 = q1.get()
st1 = time.time()
_f2 = q2.get()
et = time.time()
print("{} 耗時:{} - {}".format(time.time(), st1 - st0, et - st1))
if __name__ == '__main__':
pipe_in1, pipe_out1 = Pipe()
pipe_in2, pipe_out2 = Pipe()
p1 = Process(target=fun1, args=(pipe_in1,))
p2 = Process(target=fun2, args=(pipe_in2,))
p3 = Process(target=fun3, args=(pipe_out1, pipe_out2,))
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
代碼說明:
1、通過兩個線程不停從管道接受并寫到內(nèi)存的Queue里面,提前放到當前進程內(nèi)存里。
看一下間隔是否穩(wěn)定,部分執(zhí)行結(jié)果如下
1663139886.0722673 耗時:0.003930091857910156 - 0.005983591079711914
1663139887.6837587 耗時:0.09677457809448242 - 0.09172177314758301
1663139888.472634 耗時:0.061833858489990234 - 0.05984067916870117
1663139889.5441313 耗時:0.07132482528686523 - 0.07080578804016113
1663139890.548978 耗時:0.06183457374572754 - 0.06881546974182129
1663139891.5112402 耗時:0.0637204647064209 - 0.0718080997467041
1663139892.4756596 耗時:0.06682205200195312 - 0.06978344917297363
1663139893.5788367 耗時:0.06779074668884277 - 0.07928323745727539
時間間隔還是比較穩(wěn)定的。
總結(jié)
如果你遇到和我一樣的場景,可以仔細觀察一下進程間數(shù)據(jù)是否傳輸?shù)谋容^慢。可以考慮和我一樣的方式來解決。
原文鏈接:https://blog.csdn.net/zhiweihongyan1/article/details/126851924
相關(guān)推薦
- 2022-10-06 Python中os模塊的12種用法總結(jié)_python
- 2023-03-16 Python中的functools?partial詳解_python
- 2022-12-29 React中事件的類型定義方式_React
- 2022-10-27 Python?標準庫?fileinput與文件迭代器_python
- 2022-03-03 解決composer提示版本太舊Warning from https://mirrors.aliyu
- 2023-05-13 關(guān)于oracle數(shù)據(jù)庫表空間擴容的問題_oracle
- 2022-08-04 基于Python實現(xiàn)二維圖像雙線性插值_python
- 2022-12-10 Input系統(tǒng)之InputReader概要性實例分析_Android
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支