Matrix-Multiplikation auf der CPU (numpy) und GPU (gnumpy) geben unterschiedliche Ergebnisse
Ich bin mit gnumpy zu beschleunigen, einige Berechnungen im training eines neuronalen Netzes, indem Sie zu tun auf der GPU.
Ich bin immer die gewünschte Beschleunigung, aber bin ein wenig besorgt über die Unterschiede in den Ergebnissen von numpy (cpu) vs gnumpy (gpu).
Habe ich Folgendes test-script, um das problem zu veranschaulichen:
import gnumpy as gpu
import numpy as np
n = 400
a = np.random.uniform(low=0., high=1., size=(n, n)).astype(np.float32)
b = np.random.uniform(low=0., high=1., size=(n, n)).astype(np.float32)
ga = gpu.garray(a)
gb = gpu.garray(b)
ga = ga.dot(gb)
a = a.dot(b)
print ga.as_numpy_array(dtype=np.float32) - a
liefert die Ausgabe:
[[ 1.52587891e-05 -2.28881836e-05 2.28881836e-05 ..., -1.52587891e-05
3.81469727e-05 1.52587891e-05]
[ -5.34057617e-05 -1.52587891e-05 0.00000000e+00 ..., 1.52587891e-05
0.00000000e+00 1.52587891e-05]
[ -1.52587891e-05 -2.28881836e-05 5.34057617e-05 ..., 2.28881836e-05
0.00000000e+00 -7.62939453e-06]
...,
[ 0.00000000e+00 1.52587891e-05 3.81469727e-05 ..., 3.05175781e-05
0.00000000e+00 -2.28881836e-05]
[ 7.62939453e-06 -7.62939453e-06 -2.28881836e-05 ..., 1.52587891e-05
7.62939453e-06 1.52587891e-05]
[ 1.52587891e-05 7.62939453e-06 2.28881836e-05 ..., -1.52587891e-05
7.62939453e-06 3.05175781e-05]]
Wie Sie sehen können, die Unterschiede sind rund um die Größenordnung von 10^-5.
Also die Frage ist: sollte ich mir sorgen machen über diese Unterschiede oder ist das das erwartete Verhalten?
Zusätzliche Informationen:
- GPU: GeForce GTX 770;
- numpy version: 1.6.1
Bemerkte ich das problem wenn ich in den Gradienten-Prüfung (mit finite-Differenzen-approximation), um zu überprüfen, dass die kleinen Modifikationen, die ich gemacht, um Schalter aus numpy um gnumpy nicht etwas zu brechen. Wie kann man erwarten, dass der Verlauf der überprüfung nicht mit 32 bit Genauigkeit (gnumpy nicht unterstützt float64), aber zu meiner überraschung, der Fehler Unterschied sich zwischen CPU und GPU bei der Verwendung der gleichen Präzision.
Den Fehler auf die CPU und GPU auf einem kleinen test-neuronales Netzwerk sind unten angegeben:
Da der Fehler Größenordnungen sind ähnlich, ich vermute, dass diese Unterschiede sind OK?
Nach dem Lesen der Artikel, auf die in dem Kommentar von BenC, ich bin mir ziemlich sicher, dass die Unterschiede meist erklärt sich durch eines der Geräte mit der fused multiply-add (FMA) - Befehl, und die anderen nicht.
Implementiert habe ich das Beispiel aus dem Papier:
import gnumpy as gpu
import numpy as np
a=np.array([1.907607,-.7862027, 1.147311, .9604002], dtype=np.float32)
b=np.array([-.9355000, -.6915108, 1.724470, -.7097529], dtype=np.float32)
ga = gpu.garray(a)
gb = gpu.garray(b)
ga = ga.dot(gb)
a = a.dot(b)
print "CPU", a
print "GPU", ga
print "DIFF", ga - a
>>>CPU 0.0559577
>>>GPU 0.0559577569366
>>>DIFF 8.19563865662e-08
...und der Unterschied ist ähnlich wie FMA vs seriellen Algorithmus (wenn auch aus irgendeinem Grund die beiden Ergebnisse unterscheiden sich vom genauen Ergebnis mehr als in der Papier -).
Der GPU bin ich mit (GeForce GTX 770) unterstützt FMA-Instruktion, während die CPU nicht (ich habe ein Ivy Bridge Intel® Xeon(R) CPU E3-1225 V2, sondern führte intel den FMA3-Anweisung in Ihre Produkte mit Haswell).
Andere mögliche Erklärungen beinhalten die verschiedenen Mathematik-Bibliotheken, die verwendet im hintergrund oder Unterschiede in der Sequenz von Operationen, verursacht durch, zum Beispiel, die verschiedenen Stufen der Parallelisierung auf CPU vs GPU.
Ein Unterschied von 10^-5 kann vernachlässigbar sein oder die enorme Abhängigkeit von den Eingabedaten. Welche Größenordnung hat Ihr input-Daten haben?
der Unterschied hängt von der Größe der Eingabe. In der test-Skript die Eingabe in das Intervall [0,1]; die Ausgabe hat einen Umfang von etwa 10^2.
InformationsquelleAutor Ottokar | 2014-01-09
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde empfehlen, mit
np.allclose
für die Prüfung, ob zwei float-arrays nahezu gleich sind.In der Erwägung, dass Sie nur auf der Suche an der absolute Unterschied zwischen den Werten in den zwei Ergebnis-arrays
np.allclose
auch der Auffassung, Ihre relative Unterschiede. Nehmen wir zum Beispiel, dass die Werte in den Eingabe-arrays wurden 1000x größer - dann sind die absoluten Differenzen zwischen den beiden Ergebnissen wird auch 1000x größer, aber das bedeutet nicht, dass die beiden dot-Produkte waren weniger präzise.np.allclose
zurückTrue
nur, wenn folgende Bedingung erfüllt ist für jedes entsprechende paar von Elementen in den zwei test-arraysa
undb
:Standardmäßig
rtol=1e-5
undatol=1e-8
. Diese Toleranzen sind eine gute Daumenregel ist, sondern ob Sie sind klein genug, in deinem Fall, hängt von der jeweiligen Anwendung ab. Zum Beispiel, wenn Sie Umgang mit Werten < 1e-8, dann eine absolute Unterschied von 1e-8 wäre eine totale Katastrophe!Wenn Sie versuchen, den Aufruf
np.allclose
auf Ihre beiden Ergebnisse mit dem Standard-Toleranzen, werden Sie feststellen, dassnp.allclose
zurückTrue
. Meine Vermutung ist, dass diese Unterschiede sind wahrscheinlich klein genug, dass Sie sich keine sorgen machen muss. Es hängt wirklich davon ab, was du tust mit den Ergebnissen.InformationsquelleAutor ali_m