модуль multiprocessing
работает за счет fork
основного процесса (или выполнения большего количества копий интерпретатора Python, особенно под Windows).
поэтому вы увидите глобальные переменные, но онине будет разделяться между процессами - если вы не пойдете на специальные меры, такие как, например, явное разделение памяти.Вам лучше передать требуемое состояние в виде параметров функции (или через Pool
's initializer
и initargs
) и передать результаты обратно через возвращаемое значение.
это имеет тенденцию ограничивать вашенемного выбора дизайна, особенно если вам нужно передать много состояний (например, в качестве данных, которые вы хотите разместить)
это очень легкая оболочка для довольно низкоуровневых примитивов, следовательно, она не так интересна, как вещикак Dask
, но производительность, как правило, лучше, если вы можете жить с ограничениями
редактирования, чтобы включить некоторый демонстрационный код, который предполагает, что переменная N_mc
в вашем вопросе связана с тем, что вы выполняете какое-то монте-карло / рандомизированное приближение,Я начинаю с использования некоторых библиотек:
from multiprocessing import Pool
from PIL import Image
import numpy as np
и определяю рабочую функцию и код для ее инициализации:
def initfn(path):
# make sure worker processes don't share RNG state, see:
# https://github.com/numpy/numpy/issues/9650
np.random.seed()
global image
with Image.open(path) as img:
image = np.asarray(img.convert('L'))
def worker(i, nsamps):
height, width = image.shape
subset = image[
np.random.randint(height, size=nsamps),
np.random.randint(width, size=nsamps),
]
return np.mean(subset)
def mc_mean(path, nsamples, niter):
with Pool(initializer=initfn, initargs=(path,)) as pool:
params = [(i, nsamples) for i in range(niter)]
return pool.starmap(worker, params)
, то есть initfn
считывает файл JPEG / PNG в numpyмассив, тогда worker
просто вычисляет среднее значение (то есть яркость) для некоторого случайного подмножества пикселей.Обратите внимание, что цветные изображения загружаются в виде 3d-матриц, проиндексированных [row, col, channel]
(каналы обычно 0 = красный, 1 = синий, 2 = зеленый).Кроме того, мы также явно вызываем np.random.seed
, чтобы убедиться, что наши рабочие задания не получают одинаковую последовательность случайных значений.
Затем мы можем запустить это и построить вывод, чтобы убедиться, что все выглядит хорошо:
import scipy.stats as sps
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='ticks')
filename = 'an_image.jpeg'
result = mc_mean(filename, 1234, 56789)
# Histogram of our results
plt.hist(result, 201, density=True, alpha=0.5, edgecolor='none')
# also calculate/display expected distribution
with Image.open(filename) as img:
arr = np.asarray(img.convert('L'))
# approximate distribution of monte-carlo error
mcdist = sps.norm(np.mean(arr), np.std(arr) / np.sqrt(1234))
mn,mx = plt.xlim()
plt.xlim(mn, mx)
x = np.linspace(mn, mx, 201)
plt.plot(x, mcdist.pdf(x), '--', color='C1')
sns.despine()
, что должно дать нам что-то вроде:
очевидно, это будет зависеть от используемого изображения, это от этот JPEG .