Re: py

看板Marginalman作者 (溫水佳樹的兄長大人)時間1年前 (2024/09/25 15:23), 1年前編輯推噓1(106)
留言7則, 2人參與, 1年前最新討論串7/16 (看更多)
※ 引述《sustainer123 (溫水佳樹的兄長大人)》之銘言: : 進程(process) : 進程是載入記憶體且將執行的程式 : 打開工作管理員 : 裡面的東西就是進程 : 每個進程會被分配一個獨立id(pid) : 簡單來講 電腦執行一項任務就是一個進程 : 多進程(mutiprocessing) : 假設我們需要同時完成多個任務 : 這時候可以使用多進程 : 多進程也就是說主進程外再建立子進程 : 並且把主進程的東西整份copy過去子進程 : unix中 python可以使用fork()建立子進程 : fork()會把主進程的東西複製到子進程 : 並回傳pid到主進程與子進程 : 主進程會拿到子進程的pid : 子進程會拿到0 : 假設子進程需要主進程的pid : 可以使用get.ppid() : windows並沒有fork指令 : 我看文檔 windows只能用spawn : spawn與fork差別我沒看很懂 : 大致上就fork比較快但比較不安全 : spawn比較慢但比較安全 : 反正windows也用不到spawn以外兩種 先這樣:))) : 有興趣可以看下面網站 : 總之 我們使用multiprocessing : 我直接copy py文檔的code: : from multiprocessing import Process : import os : def info(title): : print(title) : print('module name:', __name__) : print('parent process:', os.getppid()) : print('process id:', os.getpid()) : def f(name): : info('function f') : print('hello', name) : if __name__ == '__main__': : info('main line') : p = Process(target=f, args=('bob',)) : p.start() : p.join() : 輸出: : main line : module name: __main__ : parent process: 1280 : process id: 24780 : function f : module name: __mp_main__ : parent process: 24780 : process id: 3672 : hello bob : 首先 程式執行主進程 : 之後程式執行子進程 : 這邊使用process這個類完成任務 : target是目標函數 args是傳入目標函數的參數 : p.start()是啟動子進程 : p.join()是等待子進程結束才會往下運行 : 假設一次要設置多個進程 : 我們可以使用pool 一樣使用文檔code: : from multiprocessing import Pool : def f(x): : return x*x : if __name__ == '__main__': : with Pool(5) as p: : print(p.map(f, [1, 2, 3,4,5,6])) : 這邊我有修改一下 我在list裡面多加幾個元素 : 這程式是pool池開五個進程 : 然後子進程去處理下面的程式 : 我們這邊只開五個進程 但裡面有6個元素 : 所以6必須等到有個進程被釋出 此元素才會被處理 : 一般來說 pool開的大小 == cpu核數 : 等等再寫進程間溝通跟鎖 先這樣 : 參考資料: : https://stackoverflow.com/questions/64095876/multiprocessing-fork-vs-spawn : https://docs.python.org/zh-cn/3.12/library/multiprocessing.html 接著講進程間構通 multiprocessing提供兩種方法queue與pipe doc: from multiprocessing import Process, Queue def f(q): q.put([42, None, 'hello']) if __name__ == '__main__': q = Queue() p = Process(target=f, args=(q,)) p.start() print(q.get()) # 打印 "[42, None, 'hello']" p.join() 首先創queue 之後創建子進程執行函數f 參數為queue 開始執行子進程 主進程打印q裡面的東西 這邊q.get()會等到queue裡面有東西為止 最後確認子進程結束才繼續父進程 pipe doc: from multiprocessing import Process, Pipe def f(conn): conn.send([42, None, 'hello']) conn.close() if __name__ == '__main__': parent_conn, child_conn = Pipe() p = Process(target=f, args=(child_conn,)) p.start() print(parent_conn.recv()) # 打印 "[42, None, 'hello']" p.join() 程式碼大同小異 queue跟pipe的差別在於: 假設有兩個進程或線程(thread)同時讀或同時寫會出問題 但queue沒差 使用場景可能就pipe適合只有兩個進程的溝通 queue隨便你用 再談一下鎖 有些情況下 我們會希望執行完成進程1再執行進程2 這就需要用上鎖 doc: from multiprocessing import Process, Lock def f(l, i): l.acquire() try: print('hello world', i) finally: l.release() if __name__ == '__main__': lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start() l.acquire()是獲取鎖 假設鎖被其他進程拿走 這邊就會卡著 l.release() 釋放鎖 沒這個會整個程式卡死 一定要寫 鎖大致上就長這樣 我稍微改寫一下上面的code 假設沒鎖的情況: from multiprocessing import Process def f(i): print('hello world', i) if __name__ == '__main__': for num in range(10): p = Process(target=f, args=(num,)) p.start() 輸出: hello world 1 hello world 0 hello world 2 hello world 3 hello world 4 hello world 5 hello world 6 hello world 7 hello world 8 hello world 9 假如沒有鎖 順序可能就會亂掉 多進程大抵這樣 使用場合就cpu密集任務ㄅ 不過要搞cpu密集任務 py這性能 還不如用別的語言寫 老實說 我實戰也還沒用過多進程 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.119.233.6 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Marginalman/M.1727249016.A.1D9.html

09/25 15:31, 1年前 , 1F
什麼叫同時打印
09/25 15:31, 1F

09/25 15:34, 1年前 , 2F
就正常情況下 會是一排helloworld0-9
09/25 15:34, 2F

09/25 15:35, 1年前 , 3F
我是期待會出現 helloworld1helloworld2並排的輸出
09/25 15:35, 3F

09/25 15:35, 1年前 , 4F
或者交錯的情況 我是想舉例沒鎖會發生什麼事
09/25 15:35, 4F

09/25 15:36, 1年前 , 5F
不過沒寫好 可能要再改一下或用別的例子
09/25 15:36, 5F

09/25 15:43, 1年前 , 6F
可是print不是內建一個換行符嗎 不會有並排發生吧
09/25 15:43, 6F

09/25 15:46, 1年前 , 7F
對欸 沒想清楚 這邊我再想一下怎麼改
09/25 15:46, 7F
※ 編輯: sustainer123 (140.119.233.6 臺灣), 09/25/2024 15:50:08
文章代碼(AID): #1cyxfu7P (Marginalman)
討論串 (同標題文章)
本文引述了以下文章的的內容:
1年前, 09/25
完整討論串 (本文為第 7 之 16 篇):
1
5
9月前, 03/09
2
3
1年前, 11/16
0
3
1年前, 11/12
2
2
1年前, 10/02
6
13
1
1
1年前, 09/28
1
1
2
6
0
6
1年前, 09/26
1
7
文章代碼(AID): #1cyxfu7P (Marginalman)