Czy współdzielone dane readonly są kopiowane do różnych procesów w celu przetwarzania wieloprocesowego?

Fragment kodu, który mam, wygląda trochę tak:

glbl_array = # a 3 Gb array

def my_func( args, def_param = glbl_array):
    #do stuff on args and def_param

if __name__ == '__main__':
  pool = Pool(processes=4)
  pool.map(my_func, range(1000))

Czy istnieje sposób, aby upewnić się (lub zachęcić), że różne procesy nie otrzymają kopii glbl_array, ale ją udostępniają. Jeśli nie ma sposobu, aby zatrzymać kopię, pójdę z memmapowaną tablicą, ale moje wzorce dostępu nie są zbyt regularne, więc spodziewam się, że memmapowane tablice będą wolniejsze. Powyższe wydawało się pierwszą rzeczą, aby spróbować. To jest na Linuksie. Po prostu chciałem rady od Stackoverflow i nie chcę denerwować sysadmin. Czy uważasz, że to pomoże, jeśli drugi parametr jest prawdziwym niezmiennym obiektem, takim jak glbl_array.tostring().

Author: martineau, 2011-04-05

4 answers

Możesz używać pamięci współdzielonej z multiprocessing razem z Numpy dość łatwo:

import multiprocessing
import ctypes
import numpy as np

shared_array_base = multiprocessing.Array(ctypes.c_double, 10*10)
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(10, 10)

#-- edited 2015-05-01: the assert check below checks the wrong thing
#   with recent versions of Numpy/multiprocessing. That no copy is made
#   is indicated by the fact that the program prints the output shown below.
## No copy was made
##assert shared_array.base.base is shared_array_base.get_obj()

# Parallel processing
def my_func(i, def_param=shared_array):
    shared_array[i,:] = i

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    pool.map(my_func, range(10))

    print shared_array

Które drukuje {[1]}

Jednakże, Linux ma semantykę copy-on-write na fork(), więc nawet bez użycia multiprocessing.Array, Dane nie zostaną skopiowane, chyba że zostaną zapisane.

 91
Author: pv.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-01 20:08:39

Poniższy kod działa na Win7 i Macu (może na Linuksie, ale nie testowany).

import multiprocessing
import ctypes
import numpy as np

#-- edited 2015-05-01: the assert check below checks the wrong thing
#   with recent versions of Numpy/multiprocessing. That no copy is made
#   is indicated by the fact that the program prints the output shown below.
## No copy was made
##assert shared_array.base.base is shared_array_base.get_obj()

shared_array = None

def init(shared_array_base):
    global shared_array
    shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
    shared_array = shared_array.reshape(10, 10)

# Parallel processing
def my_func(i):
    shared_array[i, :] = i

if __name__ == '__main__':
    shared_array_base = multiprocessing.Array(ctypes.c_double, 10*10)

    pool = multiprocessing.Pool(processes=4, initializer=init, initargs=(shared_array_base,))
    pool.map(my_func, range(10))

    shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
    shared_array = shared_array.reshape(10, 10)
    print shared_array
 3
Author: taku-y,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-05 14:27:06

Dla tych, którzy używają Windowsa, który nie obsługuje fork() (chyba że używają Cygwina), odpowiedź pv nie działa. Globale nie są udostępniane procesom potomnym.

Zamiast tego musisz przekazać pamięć współdzieloną podczas inicjalizacji Pool/Process jako takie:

#! /usr/bin/python

import time

from multiprocessing import Process, Queue, Array

def f(q,a):
    m = q.get()
    print m
    print a[0], a[1], a[2]
    m = q.get()
    print m
    print a[0], a[1], a[2]

if __name__ == '__main__':
    a = Array('B', (1, 2, 3), lock=False)
    q = Queue()
    p = Process(target=f, args=(q,a))
    p.start()
    q.put([1, 2, 3])
    time.sleep(1)
    a[0:3] = (4, 5, 6)
    q.put([4, 5, 6])
    p.join()

(nie jest numpy i nie jest to dobry kod, ale ilustruje punkt; -)

 2
Author: Brian White,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 15:59:07

Jeśli szukasz opcji, która działa wydajnie w systemie Windows i działa dobrze dla nieregularnych wzorców dostępu, rozgałęzień i innych scenariuszy, w których możesz potrzebować analizować różne macierze w oparciu o kombinację macierzy współdzielonej pamięci i danych lokalnych procesu, zestaw narzędzi mathDict w pakiecie ParallelRegression został zaprojektowany do obsługi tej konkretnej sytuacji.

 0
Author: RichardB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-21 22:50:10