为并行进程提供共享的只读资源
Providing shared read-only ressources to parallel processes
我正在解决一个问题,该问题允许进行一些相当没有问题的并行化。我很难弄清楚什么合适。 Python 中提供了并行化机制。我在 MacOS 上使用 python 3.9。
我的管道是:
get_common_input()
以不易并行化的方式获取一些数据。如果这很重要,它的 return 值 common_input_1
一个整数列表。
parallel_computation_1()
从列表 individual_inputs
中获取 common_input_1
和单个输入。公共输入只读。
common_input_2
或多或少是 parallel_computation_1()` 收集的输出。
parallel_computation_2()
然后再次获得 common_input_2
作为只读输入,加上一些单独的输入。
我可以做到以下几点:
import multiprocessing
common_input_1 = None
common_input_2 = None
def parallel_computation_1(individual_input):
return sum(1 for i in common_input_1 if i == individual_input)
def parallel_computation_2(individual_input):
return individual_input in common_input_2
def main():
multiprocessing.set_start_method('fork')
global common_input_1
global common_input_2
common_input_1 = [1, 2, 3, 1, 1, 3, 1]
individual_inputs_1 = [0,1,2,3]
individual_inputs_2 = [0,1,2,3,4]
with multiprocessing.Pool() as pool:
common_input_2 = pool.map(parallel_computation_1, individual_inputs_1)
with multiprocessing.Pool() as pool:
common_output = pool.map(parallel_computation_2, individual_inputs_2)
print(common_output)
if __name__ == '__main__':
main()
按照中的建议,我使用全局变量来共享数据。如果我使用 set_start_method('fork')
就可以了(这对我有用,但在 MacOS 上似乎有问题)。
请注意,如果我删除第二个 with multiprocessing.Pool()
以仅将一个池用于两个并行任务,事情将无法进行(进程看不到 common_input_2
的新值) .
除了使用全局变量对我来说似乎是糟糕的编码风格(是吗?这只是我的直觉)之外,我并不喜欢启动一个新池的需要,因为它引入了一些可能不必要的东西开销。
您如何看待这些担忧,尤其是。第二个?
有没有好的替代品?我看到我可以使用 multiprocessing.Array
,但由于我的数据是列表的列表,我需要将它展平成一个列表并以某种重要的方式在 parallel_computation
中使用它。如果我的共享输入更复杂,我将不得不付出相当多的努力将其包装到 multiprocessing.Value
或 multiprocessing.Array
中。
您可以在创建进程池之前定义和计算 output_1
作为全局变量;这样每个进程都可以访问数据;这不会导致任何内存重复,因为您没有更改该数据(写时复制)。
_output_1 = serial_computation()
def parallel_computation(input_2):
# here you can access _output_1
# you must not modify it as this will result in creating new copy in the child process
...
def main():
input_2 = ...
with Pool() as pool:
output_2 = pool.map(parallel_computation, input_2)
我正在解决一个问题,该问题允许进行一些相当没有问题的并行化。我很难弄清楚什么合适。 Python 中提供了并行化机制。我在 MacOS 上使用 python 3.9。
我的管道是:
get_common_input()
以不易并行化的方式获取一些数据。如果这很重要,它的 return 值common_input_1
一个整数列表。parallel_computation_1()
从列表individual_inputs
中获取common_input_1
和单个输入。公共输入只读。common_input_2
或多或少是 parallel_computation_1()` 收集的输出。parallel_computation_2()
然后再次获得common_input_2
作为只读输入,加上一些单独的输入。
我可以做到以下几点:
import multiprocessing
common_input_1 = None
common_input_2 = None
def parallel_computation_1(individual_input):
return sum(1 for i in common_input_1 if i == individual_input)
def parallel_computation_2(individual_input):
return individual_input in common_input_2
def main():
multiprocessing.set_start_method('fork')
global common_input_1
global common_input_2
common_input_1 = [1, 2, 3, 1, 1, 3, 1]
individual_inputs_1 = [0,1,2,3]
individual_inputs_2 = [0,1,2,3,4]
with multiprocessing.Pool() as pool:
common_input_2 = pool.map(parallel_computation_1, individual_inputs_1)
with multiprocessing.Pool() as pool:
common_output = pool.map(parallel_computation_2, individual_inputs_2)
print(common_output)
if __name__ == '__main__':
main()
按照set_start_method('fork')
就可以了(这对我有用,但在 MacOS 上似乎有问题)。
请注意,如果我删除第二个 with multiprocessing.Pool()
以仅将一个池用于两个并行任务,事情将无法进行(进程看不到 common_input_2
的新值) .
除了使用全局变量对我来说似乎是糟糕的编码风格(是吗?这只是我的直觉)之外,我并不喜欢启动一个新池的需要,因为它引入了一些可能不必要的东西开销。
您如何看待这些担忧,尤其是。第二个?
有没有好的替代品?我看到我可以使用 multiprocessing.Array
,但由于我的数据是列表的列表,我需要将它展平成一个列表并以某种重要的方式在 parallel_computation
中使用它。如果我的共享输入更复杂,我将不得不付出相当多的努力将其包装到 multiprocessing.Value
或 multiprocessing.Array
中。
您可以在创建进程池之前定义和计算 output_1
作为全局变量;这样每个进程都可以访问数据;这不会导致任何内存重复,因为您没有更改该数据(写时复制)。
_output_1 = serial_computation()
def parallel_computation(input_2):
# here you can access _output_1
# you must not modify it as this will result in creating new copy in the child process
...
def main():
input_2 = ...
with Pool() as pool:
output_2 = pool.map(parallel_computation, input_2)