Re: [問題] python multiProcess效能很差?

看板Python作者 (里歐)時間10年前 (2015/04/29 09:42), 10年前編輯推噓5(5026)
留言31則, 5人參與, 最新討論串2/4 (看更多)
經過大家的提醒,我修改了我的代碼如下 if __name__ == "__main__": content = input_file(target).split("\n") content = manager.list(content) for files in source: obj_grab.append((LogCatcher(files), content)) pool = Pool() pool.map(transferConcat, obj_grab) pool.close() pool.join() def concatMessage(logCatcher, content): for key in logCatcher.dic_map: regex = re.compile(key) for j in range(len(content)): for m in re.finditer(regex, content[j]): content[j] += logCatcher.index + obj_grab.dic_map[key] def transferConcat(args): return concatMessage(*args) 結果變82秒.... 人生已經如此的艱難... 請問這裡哪一步又做錯了呢? ------------------------------------------------------------------------ 補充:obj_grab是一個list,裡面放不同file input產生的logCatcher content是我要改的file,用manager()宣告是要讓不同process同時修改 ※ 引述《ntuleo (里歐)》之銘言: : 主要是參考segmentfault的這篇 : http://segmentfault.com/a/1190000000414339 : 看起來很有效,可是實際... : if __name__ == "__name__": : pool = Pool() : content = pool.map(transferConcat, [(obj_grab, content)])[0] : pool.close() : pool.join() : def concatMessage(obj_grab, content): : for logCatcher in obj_grab: : for key in logCatcher.dic_map: : regex = re.compile(key) : for j in range(len(content)): : for m in re.finditer(regex, content[j]): : content[j] += " " + logCatcher.index + " " + logCatcher.dic_map[key] : return content : def transferConcat(args): : return concatMessage(*args) : 以上是我的代碼(部分,只貼問題點),執行時間22秒 : 若單純執行method大概也是22秒...等於沒加速... : 我試過調整pool的數量,沒什麼效果 : 請問要怎麼做才能真正體現mulitiProcess的效能呢? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 61.221.50.98 ※ 文章網址: https://www.ptt.cc/bbs/Python/M.1430271720.A.120.html

04/29 12:48, , 1F
你可能要說明一下你的程式做了什麼,或者給個 sample
04/29 12:48, 1F

04/29 12:49, , 2F
因為我不知道怎麼把你原本的 code 跟新版的對應
04/29 12:49, 2F

04/29 12:59, , 3F
這code真是可怕…就算能動也一堆bug
04/29 12:59, 3F

04/29 13:01, , 4F
所有的process都存取同一份 content,又在迴圈裡更改迭
04/29 13:01, 4F

04/29 13:01, , 5F
代對象,太可怕了
04/29 13:01, 5F
※ 編輯: ntuleo (124.219.31.93), 04/29/2015 19:30:32

04/29 19:31, , 6F
很可怕嗎XD multiprocess不都是這樣嗎?
04/29 19:31, 6F

04/29 19:42, , 7F
都已經在用multiprocessing了還不懂得避開副作用 高手
04/29 19:42, 7F

04/29 19:45, , 8F
怎麼說呢? 可以指點我一下嗎? 我不是高手...
04/29 19:45, 8F

04/29 20:01, , 9F
你不應該嘗試去修改輸入的資料,除非是 Shared memory
04/29 20:01, 9F

04/29 20:02, , 10F
無論是 multiprocess 或者 multithread 的實作裡
04/29 20:02, 10F

04/29 20:02, , 11F
你得想辦法讓每個 process (或 thread) 各自跑各自的
04/29 20:02, 11F

04/29 20:03, , 12F
等到跑完之後,再將資料做合併,才是一個比較好的方式
04/29 20:03, 12F

04/29 20:03, , 13F
當然這個方法未必適用於你要解決的問題,只是一旦使用
04/29 20:03, 13F

04/29 20:04, , 14F
Shared memory 之後,你就得進行 Synchronization 保護
04/29 20:04, 14F

04/29 20:04, , 15F
過度的 Synchronization 會造成 CPUs 浪費時間在競爭鎖
04/29 20:04, 15F

04/29 20:05, , 16F
舉個例子來說,假設輸入是 a-z 的字串,平行的轉成大寫
04/29 20:05, 16F

04/29 20:05, , 17F
from multiprocessing.pool import ThreadPool
04/29 20:05, 17F

04/29 20:05, , 18F
pool = ThreadPool()
04/29 20:05, 18F

04/29 20:05, , 19F
print reduce(lambda x,y: x+y, pool.map(
04/29 20:05, 19F

04/29 20:05, , 20F
lambda x:x.upper(), map(chr, range(97, 123))))
04/29 20:05, 20F

04/29 20:07, , 21F
上述的範例內,輸入是一個 list (分別為 a-z 字元)
04/29 20:07, 21F

04/29 20:07, , 22F
輸出也是一個 list (已經轉成 A-Z),再用 reduce 合併
04/29 20:07, 22F

04/29 20:07, , 23F
這就是一個概念,想要平行處理就要讓 task 真正的平行
04/29 20:07, 23F

04/29 20:09, , 24F
然而上述的例子,由於並不是 CPU intensive 的計算
04/29 20:09, 24F

04/29 20:09, , 25F
開了 thread (或 process) 反而會比沒開來的慢
04/29 20:09, 25F

04/29 20:10, , 26F
我無法回答你的程式為何會如此慢,建議貼 GitHub Gist
04/29 20:10, 26F

04/29 20:11, , 27F
如果你能附上完整的程式碼,以及可重現問題的輸入資料
04/29 20:11, 27F

04/29 20:12, , 28F
相信其他板友會比較有機會能夠幫你找到問題的癥結點
04/29 20:12, 28F

04/29 20:16, , 29F
pool.map(...) 的概念是有輸入跟輸出,要特別留意這點
04/29 20:16, 29F

04/29 20:17, , 30F
另外實務上,請盡量避免使用 ThreadPool,改用 Pool
04/29 20:17, 30F

04/29 20:17, , 31F
我只是為求簡便示範給你看,以免實際程式被 GIL 給拖慢
04/29 20:17, 31F
文章代碼(AID): #1LG3Re4W (Python)
文章代碼(AID): #1LG3Re4W (Python)