2016-06-01 11 views
0

Ich habe ein Problem mit der Berechnung einer Reduzierung einer Funktion eines Netzwerks, das durch eine große (200000x200000) Matrix dargestellt wird, die als Abstandsmatrix zwischen Paaren von Punkten erzeugt wird.Tensorflow Speicherverwaltung - Chunking?

Minimal Beispiel Eingabe X einen 200000x2 numpy Array von kartesischen Koordinaten:

x = tf.constant(X[:,0], shape=[X.shape[0],1]) 
y = tf.constant(X[:,1], shape=[X.shape[0],1]) 
dx = x - tf.transpose(x) 
dy = y - tf.transpose(y) 
D = tf.sqrt(dx*dx + dy*dy) 
M = 0.1 * 5.0/tf.pow(4.0 + D, 1.5) 
res = tf.reduce_sum(betaM) 

auf der CPU läuft, den Speicher (16 GB auf meinem MBP) ist schnell überzeichnet und das System zum Stillstand kommt. Vermutlich versucht tf, das ganze D (und M?) Im Speicher zu speichern.

Wenn ich dies in C/C++ schreiben würde, würde ich höchstwahrscheinlich die Matrixzeilen überlappen, jede Zeile summieren, während ich gehe, und nie die ganze Matrix speichern. Dito die GPU - ich würde die (virtuelle) Matrix unterteilen und die Reduktion in Chunks durchführen.

Gibt es einen Trick, um tf dazu zu bringen, einem mehr stückweisen Verhalten zu folgen und dabei Speicher zu sparen?

Cheers,

Chris

EDIT:

Ein alternativer Ansatz, der mit dem Speicherproblem verkraftet verwenden tf.map_fn:

rowsums = tf.map_fn(lambda i: tf.reduce_sum(tf.sqrt(tf.reduce_sum(tf.pow(i - x,2),1))) , x) 
res = tf.reduce_sum(rowsums) 

So werden nur die rowsums als eine gespeicherte Tensor und nicht die Volldistanzmatrix. Obwohl dieser Ansatz auf der CPU gut funktioniert, kommt es auf der GPU zum Stillstand.

Antwort

1

Was hier wirklich benötigt wird (aber noch nicht implementiert ist) ist cwise fusion. Was gerade passiert, ist, dass 2*sqrt(a+b) neuen Tensor für , dann neuen Tensor für sqrt und dann noch einen für 2*sqrt zuweisen wird. PS, können Sie graben, wo der Speicher Speicherzuweisung durch die Untersuchung messages gehen wird (verbose logging brauchen)

Sie Dinge mehr Speicher effizient unter Verwendung von Variablen und assign_add inkrementell Dinge zu aktualisieren, ohne die Schaffung viele Zwischen Tensoren machen könnte. Es gibt eine alternative Formel für die Berechnung "alle paarweise Abstände" here, die einfacher zu diesem Formular zu konvertieren sein können

+0

Hallo Yaroslav, könnten Sie etwas genauer darüber sein, wie Sie Speicherverbrauch schätzen? Ich habe, dass D maximal 8 * 200000^2 ~ 300GB Speicherplatz benötigt, und etwa die Hälfte davon (die Diagonale ignorierend) als dreieckige Matrix. Vielen Dank! –

+0

Doh, ich war bei 1000. Ja, das scheint unmöglich zu speichern. Sie können Ihre Daten auf die gleiche Weise behandeln, wie TF Datensätze während des Trainings behandelt und nur in Blöcke lädt. Sie können zwei 'SliceInputProducer' +' batch' Sets verwenden, um Chunks zu erzeugen, und eine doppelt verschachtelte Schleife, um über sie zu iterieren. –

+0

Um detaillierter zu sein, könnten Sie 'SliceInputProducer' +' batch' + 'assign' verwenden, um eine Teilmenge davon zu speichern Punkte in die Variable 'subset1' bei jedem Aufruf (run1), dann haben Sie auch einen separaten 'SliceInputProducer' +' batch' + 'assign', um eine Untermenge von Punkten in die Variable 'subset2' bei jedem Aufruf (run2) zu speichern. Sie führen run1 in der äußeren Schleife und run2 in der inneren Schleife aus. Schließlich haben Sie eine Logik, die 'subset1' und' subset2' Variablen verwendet und alle paarweisen Abstände zwischen ihnen berechnet und zu Ihrem total addiert, das ist Ihr dritter Laufbefehl (run3) –