亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在Python多處理中將Pool.map與共享內存數組結合

在Python多處理中將Pool.map與共享內存數組結合

aluckdog 2019-10-17 10:22:58
我有一個很大的(只讀)數據數組,我想由多個進程并行處理。我喜歡Pool.map函數,并希望使用它來并行計算該數據上的函數。我看到可以使用Value或Array類在進程之間使用共享內存數據。但是,當我嘗試使用它時,我得到一個RuntimeError:'使用Pool.map函數時,應該僅通過繼承在進程之間共享SynchronizedString對象:這是我正在嘗試做的一個簡化示例:from sys import stdinfrom multiprocessing import Pool, Arraydef count_it( arr, key ):  count = 0  for c in arr:    if c == key:      count += 1  return countif __name__ == '__main__':  testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"  # want to share it using shared memory  toShare = Array('c', testData)  # this works  print count_it( toShare, "a" )  pool = Pool()  # RuntimeError here  print pool.map( count_it, [(toShare,key) for key in ["a", "b", "s", "d"]] )誰能告訴我我在做什么錯?因此,我想做的是在進程池中創建新的共享內存分配數組后,將信息傳遞給這些進程。
查看完整描述

3 回答

?
千萬里不及你

TA貢獻1784條經驗 獲得超9個贊

當我剛看到賞金的時候再試一次;)


基本上,我認為錯誤消息的含義是它的意思-多處理共享內存數組不能作為參數傳遞(通過酸洗)。序列化數據沒有意義-關鍵是數據是共享內存。因此,您必須使共享數組成為全局數組。我認為像我的第一個答案一樣,將其作為模塊的屬性比較整潔,但在示例中將其保留為全局變量也可以很好地工作??紤]到您不想在fork之前設置數據的觀點,這是一個修改后的示例。如果您希望擁有多個共享數組(這就是為什么要將toShare作為參數傳遞的原因),則可以類似地創建共享數組的全局列表,然后將索引傳遞給count_it(將變為for c in toShare[i]:)。


from sys import stdin

from multiprocessing import Pool, Array, Process


def count_it( key ):

  count = 0

  for c in toShare:

    if c == key:

      count += 1

  return count


if __name__ == '__main__':

  # allocate shared array - want lock=False in this case since we 

  # aren't writing to it and want to allow multiple processes to access

  # at the same time - I think with lock=True there would be little or 

  # no speedup

  maxLength = 50

  toShare = Array('c', maxLength, lock=False)


  # fork

  pool = Pool()


  # can set data after fork

  testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"

  if len(testData) > maxLength:

      raise ValueError, "Shared array too small to hold data"

  toShare[:len(testData)] = testData


  print pool.map( count_it, ["a", "b", "s", "d"] )

[編輯:以上內容由于未使用fork而無法在Windows上運行。但是,下面的方法在Windows上仍然可以使用Pool,但仍然可以使用,因此我認為這與您想要的最接近:


from sys import stdin

from multiprocessing import Pool, Array, Process

import mymodule


def count_it( key ):

  count = 0

  for c in mymodule.toShare:

    if c == key:

      count += 1

  return count


def initProcess(share):

  mymodule.toShare = share


if __name__ == '__main__':

  # allocate shared array - want lock=False in this case since we 

  # aren't writing to it and want to allow multiple processes to access

  # at the same time - I think with lock=True there would be little or 

  # no speedup

  maxLength = 50

  toShare = Array('c', maxLength, lock=False)


  # fork

  pool = Pool(initializer=initProcess,initargs=(toShare,))


  # can set data after fork

  testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"

  if len(testData) > maxLength:

      raise ValueError, "Shared array too small to hold data"

  toShare[:len(testData)] = testData


  print pool.map( count_it, ["a", "b", "s", "d"] )

不知道為什么map不會腌制數組,而Process和Pool會腌制-我想也許它已經在Windows上的子進程初始化時轉移了。請注意,盡管在派生之后仍然設置了數據。


查看完整回答
反對 回復 2019-10-17
?
蠱毒傳說

TA貢獻1895條經驗 獲得超3個贊

如果數據是只讀的,只需在從Pool派生之前將其設置為模塊中的變量即可。然后,所有子進程都應該能夠訪問它,并且只要您不對其進行寫操作,就不會被復制。


import myglobals # anything (empty .py file)

myglobals.data = []


def count_it( key ):

    count = 0

    for c in myglobals.data:

        if c == key:

            count += 1

    return count


if __name__ == '__main__':

myglobals.data = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"


pool = Pool()

print pool.map( count_it, ["a", "b", "s", "d"] )

如果您確實想嘗試使用Array,則可以嘗試使用lock=False關鍵字參數(默認情況下為true)。


查看完整回答
反對 回復 2019-10-17
  • 3 回答
  • 0 關注
  • 1207 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號