Пытаюсь снова, потому что я только что увидел награду;)
В основном я думаю, что сообщение об ошибке означает то, о чем говорилось - многопроцессорные массивы разделяемой памяти не могут быть переданы в качестве аргументов (путем травления). Нет смысла сериализовать данные - дело в том, что данные являются разделяемой памятью. Итак, вам нужно сделать общий массив глобальным. Я думаю, что лучше использовать его как атрибут модуля, как в моем первом ответе, но просто оставить его как глобальную переменную в вашем примере также хорошо. Принимая во внимание вашу точку зрения о нежелании устанавливать данные перед форком, вот модифицированный пример. Если вы хотите иметь более одного возможного общего массива (и именно поэтому вы хотели передать 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"] )
[РЕДАКТИРОВАТЬ: Вышеупомянутое не работает в Windows из-за того, что не используется fork. Однако приведенное ниже работает в 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"] )
Не уверен, почему карта не обрабатывает массив, а процесс и пул - я думаю, возможно, он был передан в точке инициализации подпроцесса в Windows. Обратите внимание, что данные все еще устанавливаются после вилки.
person
robince
schedule
12.11.2009