2012-08-02 71 views
3

我有一個Python應用程序的子例程,它接受一個八字符序列號列表,並搜索一組目錄中包含具有一系列可能擴展名的SN的文件名。它的功能如下。Python例程運行速度慢得多,多處理。池

def CompleteSN(SNorig, directories, exts, directoryContents=None): 

    # Split SNorig into its directory path and basename 
    directory, basename = os.path.split(SNorig) 

    #Don't try to complete if it has a directory already 
    if len(directory) > 0: 
     return SNorig 

    # Split the basename into extension (ext) and serial number (SN) 
    SN = basename[:8].upper() 

    #If we have a cache, check it 
    if directoryContents is not None: 
     if SN in directoryContents: 
      return directoryContents[SN] 
     else: 
      return None 

    possSNs = ['.'.join((SN, ext)) for ext in exts] 

    for pSN in possSNs: 
     for d in directories: 
      dpath = os.path.join(d, pSN) 
      if os.path.exists(dpath): 
       return dpath 

    return None 

SN是變成一個完整路徑的序列號,目錄是一個目錄列表中尋找它,EXTS是可能的擴展嘗試(不帶前導點)的名單,並directoryContents是無論是無或大(數十萬條目)字典映射目錄中的文件的序列號以搜索其全名。我的想法是,要完成大量的序列號,將所有可以找到的序列號放入字典中會更快,這樣可以快速查找它們,而不是對每個序列號進行系統調用。要完成大量的SN,這將是值得的字典的成本。如我所預料的那樣,一旦directoryContents被填充,它就快得多了。但是,只有在不使用多處理時纔是這種情況。我允許用戶切換多處理模式,當directoryContents爲None時,這種模式會更快。 (即當我們通過檢查os.path.exists檢查它們的存在來找到這些文件時)然而,在檢查它們的字典時,在多處理中調用CompleteSN.Pool的速度非常慢,每秒少於10個SN 。 (與不使用多處理時的數千人相比)我最好的猜測是,Python用來共享池工作人員之間共享數據的機制(我認爲其中有8個)正在陷入這樣一個巨大的字典結構。任何人都可以幫助我瞭解這裏發生了什麼?

+0

'os.path.exists(dpath)'運行多久?如果答案是「頻繁」,那麼這可能是問題所在。爲了確定路徑是否存在,必須查詢磁盤。爭奪磁盤訪問的多個進程可能會導致真正的減速。 – 2012-08-02 19:55:43

回答

3

通常,您不應該在多個進程之間共享數據結構。同步開銷經常會導致性能下降。也許你可以創建你的查詢字典的單個副本,每個進程一個副本?

+0

我該怎麼做一個多處理池?我將不得不單獨創建每個流程嗎? – dpitch40 2012-08-02 19:20:05

+0

手動創建每個進程肯定會起作用。我想不出一種方法來傳遞可以彌補單個查詢執行的字典......如果您創建的工作進程將多個「multiprocessing.Queue」中的下一個「SNorig」拉下來,您可以分攤成本重新創建/複製字母n/n個進程... – thebjorn 2012-08-02 19:31:36

+0

現在我只是禁用多處理時,字典填充...查找鍵這種方式是如此之快,無論如何,複製數據結構doesn'看起來值得。 – dpitch40 2012-08-02 19:39:49