再次尝试,因为我刚刚看到了赏金;)
基本上我认为错误消息的意思是它所说的 - 多处理共享内存数组不能作为参数传递(通过酸洗)。序列化数据没有意义——关键是数据是共享内存。所以你必须使共享数组成为全局的。我认为将它作为模块的属性更简洁,就像在我的第一个答案中一样,但是在您的示例中将其作为全局变量也可以很好地工作。考虑到您不想在分叉之前设置数据的观点,这是一个修改后的示例。如果您想拥有多个可能的共享数组(这就是您想将 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 不会 Pickle 数组,但 Process 和 Pool 会 - 我想它可能已经在 windows 上的子进程初始化时转移了。请注意,数据仍然在分叉之后设置。