成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

用一個開源工具實現多線程 Python 程序的可視化

開發 后端 開源
VizTracer 是一個追蹤和可視化 Python 程序的工具,對日志、調試和剖析很有幫助。盡管它對單線程、單任務程序很好用,但它在并發程序中的實用性是它的獨特之處。

[[390689]]

VizTracer 可以跟蹤并發的 Python 程序,以幫助記錄、調試和剖析。

并發是現代編程中必不可少的一部分,因為我們有多個核心,有許多需要協作的任務。然而,當并發程序不按順序運行時,就很難理解它們。對于工程師來說,在這些程序中發現 bug 和性能問題不像在單線程、單任務程序中那么容易。

在 Python 中,你有多種并發的選擇。最常見的可能是用 threading 模塊的多線程,用subprocess 和 multiprocessing 模塊的多進程,以及最近用 asyncio 模塊提供的 async 語法。在 VizTracer 之前,缺乏分析使用了這些技術程序的工具。

VizTracer 是一個追蹤和可視化 Python 程序的工具,對日志、調試和剖析很有幫助。盡管它對單線程、單任務程序很好用,但它在并發程序中的實用性是它的獨特之處。

嘗試一個簡單的任務

從一個簡單的練習任務開始:計算出一個數組中的整數是否是質數并返回一個布爾數組。下面是一個簡單的解決方案:

  1. def is_prime(n):
  2. for i in range(2, n):
  3. if n % i == 0:
  4. return False
  5. return True
  6.  
  7. def get_prime_arr(arr):
  8. return [is_prime(elem) for elem in arr]

試著用 VizTracer 以單線程方式正常運行它:

  1. if __name__ == "__main__":
  2. num_arr = [random.randint(100, 10000) for _ in range(6000)]
  3. get_prime_arr(num_arr)
  1. viztracer my_program.py

 

Running code in a single thread

調用堆棧報告顯示,耗時約 140ms,大部分時間花在 get_prime_arr 上。

 

call-stack report

這只是在數組中的元素上一遍又一遍地執行 is_prime 函數。

這是你所期望的,而且它并不有趣(如果你了解 VizTracer 的話)。

試試多線程程序

試著用多線程程序來做:

  1. if __name__ == "__main__":
  2.     num_arr = [random.randint(100, 10000) for i in range(2000)]
  3.     thread1 = Thread(target=get_prime_arr, args=(num_arr,))
  4.     thread2 = Thread(target=get_prime_arr, args=(num_arr,))
  5.     thread3 = Thread(target=get_prime_arr, args=(num_arr,))
  6.  
  7.     thread1.start()
  8.     thread2.start()
  9.     thread3.start()
  10.  
  11.     thread1.join()
  12.     thread2.join()
  13.     thread3.join()

為了配合單線程程序的工作負載,這就為三個線程使用了一個 2000 元素的數組,模擬了三個線程共享任務的情況。

 

Multi-thread program

如果你熟悉 Python 的全局解釋器鎖(GIL),就會想到,它不會再快了。由于開銷太大,花了 140ms 多一點的時間。不過,你可以觀察到多線程的并發性:

 

Concurrency of multiple threads

當一個線程在工作(執行多個 is_prime 函數)時,另一個線程被凍結了(一個 is_prime 函數);后來,它們進行了切換。這是由于 GIL 的原因,這也是 Python 沒有真正的多線程的原因。它可以實現并發,但不能實現并行。

用多進程試試

要想實現并行,辦法就是 multiprocessing 庫。下面是另一個使用 multiprocessing 的版本:

  1. if __name__ == "__main__":
  2.     num_arr = [random.randint(100, 10000) for _ in range(2000)]
  3.    
  4.     p1 = Process(target=get_prime_arr, args=(num_arr,))
  5.     p2 = Process(target=get_prime_arr, args=(num_arr,))
  6.     p3 = Process(target=get_prime_arr, args=(num_arr,))
  7.  
  8.     p1.start()
  9.     p2.start()
  10.     p3.start()
  11.  
  12.     p1.join()
  13.     p2.join()
  14.     p3.join()

要使用 VizTracer 運行它,你需要一個額外的參數:

  1. viztracer --log_multiprocess my_program.py

 

Running with extra argument

整個程序在 50ms 多一點的時間內完成,實際任務在 50ms 之前完成。程序的速度大概提高了三倍。

為了和多線程版本進行比較,這里是多進程版本:

 

Multi-process version

在沒有 GIL 的情況下,多個進程可以實現并行,也就是多個 is_prime 函數可以并行執行。

不過,Python 的多線程也不是一無是處。例如,對于計算密集型和 I/O 密集型程序,你可以用睡眠來偽造一個 I/O 綁定的任務:

  1. def io_task():
  2.     time.sleep(0.01)

在單線程、單任務程序中試試:

  1. if __name__ == "__main__":
  2.     for _ in range(3):
  3.         io_task()

 

I/O-bound single-thread, single-task program

整個程序用了 30ms 左右,沒什么特別的。

現在使用多線程:

  1. if __name__ == "__main__":
  2.     thread1 = Thread(target=io_task)
  3.     thread2 = Thread(target=io_task)
  4.     thread3 = Thread(target=io_task)
  5.  
  6.     thread1.start()
  7.     thread2.start()
  8.     thread3.start()
  9.  
  10.     thread1.join()
  11.     thread2.join()
  12.     thread3.join()

 

I/O-bound multi-thread program

程序耗時 10ms,很明顯三個線程是并發工作的,這提高了整體性能。

用 asyncio 試試

Python 正在嘗試引入另一個有趣的功能,叫做異步編程。你可以制作一個異步版的任務:

  1. import asyncio
  2.  
  3. async def io_task():
  4.     await asyncio.sleep(0.01)
  5.  
  6. async def main():
  7.     t1 = asyncio.create_task(io_task())
  8.     t2 = asyncio.create_task(io_task())
  9.     t3 = asyncio.create_task(io_task())
  10.  
  11.     await t1
  12.     await t2
  13.     await t3
  14.  
  15. if __name__ == "__main__":
  16.     asyncio.run(main())

由于 asyncio 從字面上看是一個帶有任務的單線程調度器,你可以直接在它上使用 VizTracer:

 

VizTracer with asyncio

依然花了 10ms,但顯示的大部分函數都是底層結構,這可能不是用戶感興趣的。為了解決這個問題,可以使用 --log_async 來分離真正的任務:

  1. viztracer --log_async my_program.py

 

Using --log_async to separate tasks

現在,用戶任務更加清晰了。在大部分時間里,沒有任務在運行(因為它唯一做的事情就是睡覺)。有趣的部分是這里:

 

Graph of task creation and execution

這顯示了任務的創建和執行時間。Task-1 是 main() 協程,創建了其他任務。Task-2、Task-3、Task-4 執行 io_task 和 sleep 然后等待喚醒。如圖所示,因為是單線程程序,所以任務之間沒有重疊,VizTracer 這樣可視化是為了讓它更容易理解。

為了讓它更有趣,可以在任務中添加一個 time.sleep 的調用來阻止異步循環:

  1. async def io_task():
  2.     time.sleep(0.01)
  3.     await asyncio.sleep(0.01)

 

time.sleep call

程序耗時更長(40ms),任務填補了異步調度器中的空白。

這個功能對于診斷異步程序的行為和性能問題非常有幫助。

看看 VizTracer 發生了什么?

通過 VizTracer,你可以在時間軸上查看程序的進展情況,而不是從復雜的日志中想象。這有助于你更好地理解你的并發程序。

VizTracer 是開源的,在 Apache 2.0 許可證下發布,支持所有常見的操作系統(Linux、macOS 和 Windows)。你可以在 VizTracer 的 GitHub 倉庫中了解更多關于它的功能和訪問它的源代碼。

 

責任編輯:龐桂玉 來源: Linux中國
相關推薦

2020-04-10 14:20:47

算法可視化Github

2019-09-27 09:12:18

開源數據可視化大數據

2017-06-19 08:30:35

大數據數據可視化報表

2021-02-21 08:11:46

PythonDash工具

2023-02-21 08:02:09

可視化工具圖表

2022-06-20 09:45:48

Python開源可視化庫

2022-05-24 15:03:44

開源工具可視化

2021-06-09 11:26:37

BokehPython可視化

2017-07-10 14:18:34

微服務架構可視化

2017-10-14 13:54:26

數據可視化數據信息可視化

2022-08-26 09:15:58

Python可視化plotly

2022-07-07 08:50:26

Python可視化模塊代碼

2022-04-20 20:30:36

可視化模塊Python

2023-04-14 08:21:55

2022-01-17 09:22:42

SwiftUI App Store開源

2019-08-06 10:35:25

Python時間序列可視化

2021-03-30 10:30:27

Charts.css可視化前端

2022-08-23 12:32:37

Python可視化圖表

2021-03-17 08:07:56

Python可視化工具

2020-05-19 11:46:50

MongoDB圖形開源
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99国内精品久久久久久久 | 久久精品国产免费 | 丁香五月网久久综合 | 欧美一区二区在线播放 | 99re在线视频 | 成人欧美一区二区三区黑人孕妇 | 欧美成人二区 | 久久黄视频 | 国产在线1区 | 国产成人网 | 免费在线观看h片 | 91精品一区 | 国产偷自视频区视频 | 国产2区| 亚洲一区二区免费视频 | 久久9视频| 国产91在线 | 中日 | av毛片在线| 中文字幕一级毛片 | 99爱在线| 99视频精品 | 午夜小影院 | 黄色在线 | 狠狠艹| 国产成人精品一区二区 | 一本大道久久a久久精二百 国产成人免费在线 | 久久久久成人精品亚洲国产 | 欧美一级特黄aaa大片在线观看 | 国户精品久久久久久久久久久不卡 | 亚洲国产aⅴ成人精品无吗 国产精品永久在线观看 | 精品粉嫩aⅴ一区二区三区四区 | 亚洲成人三级 | 欧美久久免费观看 | 亚洲黄色一级 | 欧美中文字幕一区二区三区亚洲 | 日韩在线免费 | 日本精品久久 | 亚洲综合在线视频 | 国产一级在线 | 在线色网 | 九九精品在线 |