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:
Matrix-Multiplikation auf der CPU (numpy) und GPU (gnumpy) geben unterschiedliche Ergebnisse

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.

Hier ist eine gute Lektüre für Sie: Präzisions - & Leistung: Gleitkomma und IEEE 754-Compliance für NVIDIA-GPUs
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

Schreibe einen Kommentar