PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : digit life PS Precision Test Messmethode


Demirug
2003-06-18, 10:14:28
Dem Test liegt ja eine Datei "PSShaders.txt" bei und ich gehe jetzt mal davon aus das die Shader welche dort enthalten sind auch benutzt werden.


;### Rxx_Mantissa
ps_2_0
def c0, 0.0f, 1.0f, %sf, 2.0f
mov r0, c0.y // mov r0, 1
mov r1, c0.z
add_pp r0, r0, r1 // + BIG NUMBER (but itself lower precision)
sub_pp r0, r0, r1 // - BIG NUMBER (but itself lower precision
mov_pp oC0, r0

;### Rxx_Exponent
ps_2_0
def c0, 1.0f, %sf, 16.0f, 0.125001f
mov r0, c0.y // mov r0, x
mul_pp r0, r0, r0 // mul r0, // r0 = x*x
rcp_pp r2, r0.x // mov r2, // r2 = 1/(x*x)
mul_pp r0, r0, r0 // mul r0, // r0 = x*x*x*x
mul_pp r0, r0, r2 // mul r0, r0, 1/(x*x)
mul_pp r0, r0, r2 // mul r0, r0, 1/(x*x)
mov_pp oC0, r0

;### ==========================================

;### Cxx_Mantissa
ps_2_0 // def c0, 0.0f, 1.0f, pp, pp+1
def c0, 0.0f, 1.0f, %sf, %sf
mov_pp r0, c0.w
mov_pp r1, c0.z
sub r0, r0, r1
mov oC0, r0

;### Cxx_Exponent
ps_2_0
def c0, 0.5f, %sf, %sf, 2.0f // 0.5f, x==y^^precision, Sqrt(x), 2.0f
mov_pp r0, c0.y // mov r0, x
mov_pp r1, c0.z // mov r1, Sqrt(x)
mul r0, r0, r1
mul r0, r0, r1
rcp r1, r0.x
min r0, r0, r1
mov oC0, r0 // if enought precision then == 1 else << 1

;### ==========================================

;### Txx_Mantissa
ps_2_0
dcl_pp t0.rg
mov r0.xy, t0
sub r0, r0.y, r0.x
mov oC0, r0

;### Txx_Exponent
ps_2_0
dcl_pp t0.rg
//def c0, 1.0f, 1.0f, 0.0f, 2.0f
mov r0.xy, t0

mul r1, r0.x, r0.y
mul r0, r1, r0.y
rcp r1, r0.x
min r0, r0, r1
//sub r0, c0.x, r1
mov oC0, r0


;### ==========================================
;### Rxx_Mantissa_BIG
ps_2_0
def c0, 0.0f, 1.0f, %sf, 2.0f
mov r0, c0.y // mov r0, 1
mov r1, c0.z // mov r1, 4096

//add_pp r0, r0, r1 // + BIG NUMBER (but itself lower precision)
//sub_pp r0, r0, r1 // - BIG NUMBER (but itself lower precision

add_pp r2, r0, r1 // + BIG NUMBER (but itself lower precision)
add_pp r3, r0, r1 // + BIG NUMBER (but itself lower precision)
add_pp r4, r0, r1 // + BIG NUMBER (but itself lower precision)
add_pp r5, r0, r1 // + BIG NUMBER (but itself lower precision)

sub_pp r2, r2, r1 // - BIG NUMBER (but itself lower precision
sub_pp r3, r3, r1 // - BIG NUMBER (but itself lower precision
sub_pp r4, r4, r1 // - BIG NUMBER (but itself lower precision
sub_pp r5, r5, r1 // - BIG NUMBER (but itself lower precision

add_pp r0, r2, r3
add_pp r1, r4, r5
add_pp r0, r0, r1

mov_pp oC0, r0


Es stellt sich mir aber nun die Frage wie das messe der Genauigkeit auf diese Art und weise funktionieren soll. Da bei jedem Shader Tempregister (r#) eine Rolle spielen kann die Genauigkeit bei den Texturkorrdinaten (t#) und Konstanten (c#) niemals höher als bei dem Temps sein. Mit fp16 wären die Temps ja aber sowieso zu ungenau würde da nicht mein zweites Problem ins Spiel kommen.

In der Spec steht ja noch diese nette Hintertür:

Implementations vary precision automatically based on precision of inputs to a given op for optimal performance.

Die Frage ist nun was ist die "precision of inputs" in diesem Zusammenhang? Die Genauigkeit des Registers aus dem der Wert geholt wird oder die Genauigkeit des Wertes welcher sich in dem Register befindet?

Zur Erklärung des unterschieds:


dcl_pp t0.rg (1)
mov r0.xy, t0 (2)
sub r0, r0.y, r0.x (3)


1. Mit dieser Zeile wird für t0 (Texturecoordinate) die reduzierte Genauigkeit erlaubt.

2. t0 (reduzierte genauigkeit) wird noch r0 koppiert (mov). in r0 (Tempregister soll fp24 sein) ist also nun ein Wert mit reduzierter Genauigkeit gespeichert.

3. gehen wir hier von dem Inhalt des r0 Register aus darf die Subtraktion (sub) mit reduzierter Genauigkeit durchgeführt werden gehen wir allerdings von dem Registertype aus muss sie mit normaler Genauigkeit durchgeführt werden. Abhängig von der Antwort auf diese Frage ergibt sich ob man nach dem durchführen der Operation in r0 ein Wert mit normaler oder reduzierter Genauigkeit findet.

Dieses Kettenspiel (wenn es erlaubt ist) könnte man dann sehr gut weiter spielen bis man am ende bei einem Shader landet der komplett nur mit reduzierter Genauigkeit arbeitet.

Noch zur Erklärung:

Ich hege keine Zweifel daran das nv bei den NV3X (x < 5) Chips unter DX die Tempregister in aller Regel nur mit reduzierter Genauigkeit laufen lässt. Bei den Konstanten dürfen sie das ja sowieso. Die Frage die ich mir nur Stelle ist in wie weit die Messmethode von digit-life als verlässlich anzusehen ist und ob dieses fp16 rechnen durch die Spec aufgrund der Hintertür nicht doch legal ist.

Gast
2003-06-18, 10:23:33
Original geschrieben von Demirug

Ich hege keine Zweifel daran das nv bei den NV3X (x < 5) Chips unter DX die Tempregister in aller Regel nur mit reduzierter Genauigkeit laufen lässt. Bei den Konstanten dürfen sie das ja sowieso. Die Frage die ich mir nur Stelle ist in wie weit die Messmethode von digit-life als verlässlich anzusehen ist und ob dieses fp16 rechnen durch die Spec aufgrund der Hintertür nicht doch legal ist.

Auch wenn es durch 3 hintertürchen und der unausweichlich folgenden Wortverdreherei irgendwie "legal" sein sollte, ist es den wünschenswert? Im Allgemeinen sitzen hier nämlich keine Anwälte.

Demirug
2003-06-18, 11:00:47
Original geschrieben von Gast
Auch wenn es durch 3 hintertürchen und der unausweichlich folgenden Wortverdreherei irgendwie "legal" sein sollte, ist es den wünschenswert? Im Allgemeinen sitzen hier nämlich keine Anwälte.

Ist es wünschenswert? Gute Frage.

In den wenigsten Fällen wird es zwischen FP16/FP24/FP32 sichtbare unterschiede geben aber diese Fälle gibt es und je länger und komplexer die Shaderprogramme werden desto höher steigt die Wahrscheinlichkeit dafür.

Die beste Lösung wäre wohl eine Option in Panel ob man schnelle oder genaue Shaderberechungen haben möchte. Dann kann jeder seine Wahl treffen auf was er mehr Wert legt.

Bringhimup
2003-06-18, 14:38:55
Dann gibts auch wieder die 2 altbekannten Lager die sich streiten welches der Beste Default-Wert ist.

aths
2003-06-18, 15:19:12
Demirug,

ich denke, Leo hat das in seiner News sehr gut formuliert: Nvidia _wirbt_ großartig mit den ach so tollen 32 Bit, und liefert auf den meisten Karten nur 16. Dass die HW 32 Bit kann, ist klar, aber der Kunde hat davon nichts. Das ist eine Form des Marketings, die dem Kunden sauer aufstößt - ein Feature groß bewerben und es dann abschalten.

Demirug
2003-06-18, 15:22:11
Original geschrieben von aths
Demirug,

ich denke, Leo hat das in seiner News sehr gut formuliert: Nvidia _wirbt_ großartig mit den ach so tollen 32 Bit, und liefert auf den meisten Karten nur 16. Dass die HW 32 Bit kann, ist klar, aber der Kunde hat davon nichts. Das ist eine Form des Marketings, die dem Kunden sauer aufstößt - ein Feature groß bewerben und es dann abschalten.

Mit den 44.10 scheint es ja zumindestens bei einigen doch mit 32 bit zu laufen.

aths
2003-06-18, 15:24:19
Original geschrieben von Bringhimup
Dann gibts auch wieder die 2 altbekannten Lager die sich streiten welches der Beste Default-Wert ist. Wenn ich das richtig verstanden habe, könnte man Shader so schreiben, dass sie auf 16 Bit Genauigkeit Rücksicht nehmen. Das hielte ich natürlich für effizienter, als dass "rücksichtslose" Shader geschrieben würden, die 24 oder 32 Bit brauchen damit die Effekte gut aussehen. Demirug könnte hier sicherlich mehr sagen.

zeckensack
2003-06-18, 18:16:27
Demirug,

Ich habe mal frei hervorgehoben ;)
"Implementations vary precision automatically based on precision of inputs to a given op for optimal performance."

Ich interpretiere das nun so, daß die Präzision mit der eine Operation ausgeführt wird variabel sein darf.
Vgl etwa die PFRCP/PFRCPIT1/PFRCPIT2-Instruktionen in 3DNow!, die es erlauben die Präzision des Ergebnisses zu steuern (im Austausch gegen Instruktionsanzahl und natürlich Taktzyklen). Trotzdem arbeiten sie immer mit 32bittigen Registern (resp 32bittigen Feldern innerhalb der SIMD-Register).

Genau so stelle ich mir auch die Intention von MS vor, die Temp-Register (und damit alle Rechenergebnisse) sollen schließlich immer mindestens 24bittig sein. Das steht klar im Text, da gibt es nichts zu deuteln. Das einzige was ich somit überhaupt variieren kann ist die Präzision der Berechnung selbst, ausdrücklich nicht das Datenformat, in welchem das Ergebnis gespeichert wird.

Btw, die Betrachtung des Zielformats ist hier irrelevant, denn eine 32bit-Berechnung in ein 16bit-Register zu schreiben ist sinnlos, umgekehrt stellt sich wieder die Frage der geforderten Berechnungspräzision. 32bittige Register können selbstverständlich auch Ergebnisse aufnehmen, die nur 16 Bits 'Nährwert' haben, aber das muß man nicht weiter betrachten.

Die Kriterien dazu stehen auch da: die Präzision der Inputs für die gerade betrachtete Operation.

So, das führt jetzt zur nächsten offenen Frage: definiert sich Präzision als 'Datenformat' oder als 'Anzahl der signifikanten Bits'?

Natürlich habe ich auch schon eine Antwort parat :naughty: :D
Da nur Konstanten überhaupt reduzierte Präzision haben dürfen, können nur Operationen die ausschließlich Konstanten verknüpfen 'wenig signifkante Bits' erzeugen. Diese Klasse der Operationen ist aber per se überflüssig, und gehört wegoptimiert (3*5=15, das brauche ich nicht in einem Shader auszurechnen, das weiß ich vorher).

edit: Auch wenn wir diese Regel durch _pp brechen, das Ergebnis einer Operation auf 16bittigen Operanden ist oft eben nicht mehr verlustfrei auf 16 Bits reduzierbar.

Von daher, IMO, gibt es überhaupt keine Grundlage für 'Flußanalyse', um irgendwie herauszufinden welche Operationen ich 'halbdoof' ausführen darf und welche nicht. Da wo ich etwas finde, ist dies nur ein Anzeichen für das Versagen des Compilers.

Das ganze lässt sich einfach nicht mit dem Text von MS - so er denn noch aktuell gültig ist - vereinbaren.

Demirug
2003-06-18, 18:31:27
zeckensack, ich sehe das ja genauso. Aber es ist eben leider nicht absolute eindeutig und wir wissen ja:

"Wenn du einen Vertrag nicht brechen kannst interpretiere ihn."

Das Problem scheint aber sowieso ein zeitlich begrennztes zu sein weil die neusten Treiber wohl auf fp32 machen.

Xmas
2003-06-18, 19:00:19
Original geschrieben von zeckensack
Natürlich habe ich auch schon eine Antwort parat :naughty: :D
Da nur Konstanten überhaupt reduzierte Präzision haben dürfen, können nur Operationen die ausschließlich Konstanten verknüpfen 'wenig signifkante Bits' erzeugen. Diese Klasse der Operationen ist aber per se überflüssig, und gehört wegoptimiert (3*5=15, das brauche ich nicht in einem Shader auszurechnen, das weiß ich vorher).
Die zwei Color-Register und die Sampler-Register (je nach Texturformat) können auch reduzierte Präzision haben.