R
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