Präzision von Matlab und openCL



  • Tim schrieb:

    Ist die Implementierung in OpenCL nun in float oder double?

    opencl kennt 16bit bis zu 128bit gleitkommazahlen
    wird man wohl vermutlich wählen können zwischen float und double und höher.
    http://de.wikipedia.org/wiki/OpenCL



  • Nachdem der OP nur von float und double geredet hat gehe ich schon davon aus, dass er maximal diesen beiden probiert hat.



  • Was Berechnest du denn? IEEE754 vorausgesetzt, kannst du nur für +-*/ und sqrt gleiche Ergebnisse erwarten.


  • Mod

    Beim GCC kannst du beispielsweise mit der Option -ffloat-store steuern, dass Fließkommawerte nicht direkt aus den CPU-Registern weiter verarbeitet werden, sondern zwischendurch auf normale double-precision gestutzt werden. Ich könnte mir nämlich vorstellen, dass die Abweichungen daher kommen, da eine x86-CPU intern genauer als double-precision rechnen kann, eine Softwareemulation auf der Grafikkarte dies jedoch wohl kaum tun wird.

    Auch interessant sind die Optionen -fexcess-precision (wie ffloat-store, aber mit mehr Feintuning), -mfpmath (Festlegung, welche Register benutzt werden dürfen, 387-FPU und SSE haben unterschiedliche Genauigkeit!) und allgemein die ganzen Optionen für x86 und x86-64, mit denen man noch mehr Feintuning betreiben kann.

    Andere Compiler haben sicherlich ähnliche Optionen.



  • stdieee schrieb:

    Was Berechnest du denn? IEEE754 vorausgesetzt, kannst du nur für +-*/ und sqrt gleiche Ergebnisse erwarten.

    interessant, und wie kommt das?



  • ganz dick.
    es kommt gaaanz dick!
    🙂


  • Administrator

    1. http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (gibt es irgendwo auch als PDF)
    2. http://randomascii.wordpress.com/category/floating-point/
    bzw.
    http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

    Wie vergleiche ich? Meistens mit ULP und einem vernünftigen Threshold. Und den folgenden Spezialfall:

    if(left == 0.0 || right == 0.0)
    {
      printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARGH!!!!!");
    }
    

    🤡

    Grüssli



  • Matlab rechnet standardmäßig mit double. OpenCL bevorzugt float. Zwar ist double möglich aber die Performance bricht ein. Siehe http://en.wikipedia.org/wiki/Nvidia_Tesla#Tesla_overview.

    Bis das openCL-Program fertig ist kann ich dennoch mit double rechnen. Ist es dann getestet würde ich alle double's durch float's ersetzen. Mittels Präprozessor kein großes Ding.

    Aber selbst mit diesem ekeligen Trick sind die Ergebnisse nicht identisch.

    Die Compiler-Flags die SeppJ genannt hat werde ich mir genauer ansehen. Vielleicht ist da was dabei.

    Besten Dank!


  • Mod

    goran schrieb:

    Matlab rechnet standardmäßig mit double.

    Ich habe irgendwie den Eindruck, dass du das Problem nicht ganz verstanden hast, welches die Antwortenden hier im Thread vermuten. Anstatt es noch einmal darzulegen, verlinke ich stattdessen einen Unterlink aus Draveres Beitrag:
    http://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/



  • Ein Hinweis aus eigener Erfahrung: Bei der parallelen Berechnung eines Skalarproduktes großer Vektoren wird typischerweise eine Reduktion durchgeführt, die zu einer anderen Reihenfolge der Operation führt. Konkret:

    Parallel
    x = (a+b) + (c+d)

    Sequentiell
    x = ((a + b) + c) + d

    Da die Addition mit floats nicht (!) assoziativ ist werden die Ergebnisse nicht vergleichbar sein. (Die parallele Version kann sogar genauer sein, d.h. weniger anfällig für Rundungsfehler.)

    Da Du aber nicht beschreibst, was Du portierst, sondern nur dass Du portierst lässt ggf. das eigentliche Problem im dunkeln 😉



  • goran schrieb:

    Hallo allerseits,

    ich habe ein Problem beim Übersetzen von Matlab nach C/openCL. Der Matlab-Code bzw. die Matlab-Ergebnisse dient bzw. dienen als Referenz-Design. Soweit so gut.

    Übersetze ich Matlab-Code nach C sind die Ergebnisse für double oder float identisch und ich bin sicher keinen Bug zu haben.

    Übersetze ich Matlab-Code nach openCL beginnen meine Probleme.

    lass mich raten, die opencl implementation testest du aber nicht mehr auf der referenz hardware (sprich deiner cpu) sondern auf einer anderen hardware (z.b. gpu)?

    dein problem ist vermutlich nicht software, sondern hardware bedingt. lass opencl auf der cpu laufen und verifiziere dass dasselbe rauskommt.

    Die Ergebnisse für float oder double (double auf openCL ist böse) sind unterschiedlich.

    double ist nicht boese, double ist double und das tangiert opencl peripher.
    wenn du es auf deiner CPU laufen laesst, erreichst du vermutlich genau das selbe leistungsverhaeltnis zwischen double und float wie bei der c loesung. willst du es schneller haben, brauchst du eine entsprechend teure hardware bei opencl. eine 7970 von ATI duerfte 1TFlop fuer ca 300euro bieten, bei double. GTX680 von nvidia ca 0.25TFlop fuer 400, eine NVidia Tesla K20 bietet 1.25TFlop fuer ca 3000euro.

    Mittlerweile glaube ich keine identischen Ergebnisse erhalten zu können. Aber sehr ähnliche.

    versuch mal dein c program auf einer cpu eines anderen herstellers laufen zu lassen, koennte sein dass selbst da schon fehler vorhanden sind.

    Wie überprüft ihr bzw. würdet überprüfen ob der openCL-Code der Matlab-Referenz bei Berücksichtigung der Rundungsungenauigkeiten von float und double entspricht?

    das problem ist deine definition von referenzdesign. du musst bei flieskommazahlen eine gewisse fehlertolleranz erlauben. es gibt bei IEEE754 genaue vorgaben wieviel pro operation erlaubt sind, du musst also bei deinem ergebnis die operationen zaehlen und ihre fehlerquote verrechnen.

    schau dir auch die optimierungsflags deines opencl compilers an, die meisten sind sehr aggresive eingestellt und benutzen z.b. MADD statt FMA und andere tricks (z.b. nutzt nvidia bei der division __fdivf und wie du dort lesen kannst, gibt es in der doku eine extra annotation ueber die verminderte genauigkeit.

    du kannst auch selbst dafuer sorgen dass genaue ergebnisse rauskommen, indem du die operationsreihenfolge bestimmts, z.b. ein dot mit x*x+y*y+z*z+w*w zu schreiben, kannst du es mit x*x+y*y+(z*z+w*w) und entsprechend strikten treiber flags so optimieren (auf genauigkeit). steht alles in den IEEE754 🙂


Anmelden zum Antworten