2016-08-30 4 views
1

Ich habe ein numpy Array (Matrix), die ich mit berechneten Werten asynchron füllen möchte. Als Ergebnis möchte ich Matrixabstände mit berechneten Werten haben, aber am Ende erhalte ich eine Matrix, die mit dem Standardwert (-1) gefüllt ist. Ich verstehe, dass etwas mit dem Teilen von Distanzen zwischen Threads falsch ist, aber ich kann nicht herausfinden, was genau falsch ist.Gemeinsames numpy Array mit Multithreading

import numpy as np 
import concurrent.futures 

data = range(1, 10) 
amount = len(data) 
default = -1 
distances = np.full((amount, amount), default, dtype=np.float32) 


def calculate_distance(i, j): 
    global distances 
    if i == j: 
     distances[i][j] = 0 
    else: 
     calculated = data[i] + data[j] #doesn't matter how is this calculated 
     distances[i][j] = calculated 
     distances[j][i] = calculated 


with concurrent.futures.ProcessPoolExecutor() as executor: 
    for i in range(0, amount): 
     for j in range(i, amount): 
      future = executor.submit(calculate_distance, i, j) 
      result = future.result() 

executor.shutdown(True) 
print(distances) 
+0

Sie verwenden Prozesse, nicht Threads. Ich nehme an, dass Sie eine Umgebung verwenden, die Forking unterstützt. Dies bedeutet, dass Sie Prozesse erhalten, die eine Kopie von "Distanzen" haben (eigentlich vom Speicher im Allgemeinen). Wenn diese Prozesse "Distanzen" modifizieren, modifizieren sie ihre eigene Kopie. Dies ist eine Vereinfachung, da Copy-on-Write beteiligt sein kann, aber das Endergebnis ist das gleiche. –

+0

Sie könnten sich auch für dieses Q/A in Bezug auf schreibgeschützte Shared Numpy Arrays für die Verwendung zwischen Prozessen interessieren: http://StackOverflow.com/questions/17785275/share-large-read-only-numpy-array-between-multiprocessing -Prozesse. –

+0

Wenn Sie den 'ProcessPoolExecutor' verwenden, müssen Sie zuerst einen 'if __name__ ==" __main __ "' Wächter einfügen, sonst funktioniert Ihr Code nicht auf allen Plattformen. Zweitens warten Sie, bis jede Aufgabe abgeschlossen ist, bevor Sie die nächste Aufgabe absetzen, sodass die Aufgaben nacheinander ausgeführt werden. Drittens können Sie mit Threads im Allgemeinen aufgrund der Global Interpreter-Sperre keine Prozessorzeit für Python-Code erhalten. –

Antwort

0

Sie verwenden eine ProcessPoolExecutor. Dies wird neue Prozesse für die Ausführung von Arbeiten forkieren. Diese Prozesse teilen keinen Speicher, sondern erhalten jeweils eine Kopie der distances Matrix.

Daher werden alle Änderungen an ihrer Kopie sicherlich nicht im ursprünglichen Prozess widergespiegelt werden.

Verwenden Sie stattdessen eine ThreadPoolExecutor.

HINWEIS: Globals werden in der Regel mit Widerwillen angesehen ... übergeben Sie das Array stattdessen in die Funktion.