Inside nVidia NV40
14. April 2004 / von aths / Seite 2 von 6
Eine einzelne NV40-Pipe im Detail
Unser Bild der Pipe ist vereinfacht, um nicht in zu vielen Details zu ersticken. Außerdem betrachten wir lediglich DirectX9-Shaderpower.
Eine einzelne NV30-Pipe kann zwei Textur-Operationen, oder (jede) arithmetische Instruktion ausführen. Diese ganze Arbeit wird im Shader Core verrichtet. Einige Spezialfunktionen benötigen mehrere Takte. Eine Textur-Operation liefert das fertige Textursample nicht sofort, wenn man besser als bilinear filtert, muss die Pipe ihre beiden TMUs nutzen, in einigen Fällen sind auch interne Loops notwendig. Weil das tatsächliche Sampling gewöhnlicherweise länger dauert als die Berechnungen für die Textur-Operation, zählen wir grundsätzlich die Sampling-Leistung und kommen auf 2T+1M.
Eine einzelne NV35-Pipe kann alles bisher gesagte und zusätzlich seine neue FPU nutzen. Diese Einheit bringt abhängig vom Shader-Code ein oder zwei zusätzliche arithmetische Instruktionen pro Takt. Die FPU-Verbesserungen der arithemischen Power sind auf MAD-Operationen begrenzt. MAD ist die Abkürzung für Multiply-Add. Multiply (MUL), ADD, und Multiply-Add sind sehr gebräuchliche Operationen und werden oft genutzt. Eine NV35-Pipe liefert ungefähr 2T+2M, und mit seinen 4 Pipes ingesamt 8T+8M.
Eine einzelne NV40-Pipe kann folgendes tun: In Shader Unit 1 (bislang bekannt als "Shader Core") entweder eine Textur-Operation, eine Multiplikation, oder eine Spezialfunktion. Shader Unit 2 (die bisherige "FPU") kann noch eine beliebige MAD-Operation beisteuern. Das beinhaltet Dot3, was für Dot3-Lighting und Bumpmapping wichtig ist. Doom3 nutzt kräftig Dot3-Bumpmapping. Es ist gut möglich, dass Shader Unit 2 auch einige Spezialfunktionen berechnen kann, für solche Untersuchungen hatten wir nicht genügend Zeit. Man sollte aber bedenken, dass wir den logischen Pipeline-Aufbau besprechen, die tatsächliche Hardware arbeitet womöglich ganz anders.
Jede NV40-Pipe besteht aus zwei Shader Units.
- Die Abkürzungen:
- "MUL": Multiplikation
- "SFU": Spezialfunktionen (wie RCP und RSQ, das wären 1/x und 1/√ x)
- "MAD": Multiply-Add, "Dot": Jedes Skalarprodukt (mit zu vier Komponenten pro Vektor.)
- "Texture" heißt Textur-Operation. So eine Operation stößt die Filterung eines Textursamples an. (Vor der eigentlichen Filterung müssen noch bestimmte Rechnungen gemacht werden.)
Nun, die ganze Wahrheit ist schon etwas komplizierter. Außerdem kennen wir jetzt noch nicht jedes einzelne Detail. Wir erwarten, dass die letzten Geheimnisse dann in Tech-Papieren für Entwickler offenbart werden. Diskutieren wir trotzdem unser vereinfachtes Diagramm, um dann den Blick auf ein vollständigeres Bild zu wenden.
Jede Pipe hat seine beiden Shader Units. Das gute ist, dass jede einzelne Unit bis zu zwei unabhängige Befehle pro Takt ausführen kann. Das geschieht per Split. Ein voller Pixel-Vektor besteht aus 4 Einzelwerten (und zwar: rot, gründ und blau für die Farbe, umd Alpha für Transparenz oder andere Spezialeffekte.) Jede Einheit kann in 3:1 splitten (seit Radeon 9500 beherrscht ATI das auch, was wir erwähnen sollten) oder in 2:2 (das ist NV40-exklusiv.) Damit ist es möglich, zwei der DP2-Befehle zu bundeln. Und weil einige Berechnungen die Textur-Sampleposition ändern (was meist ein Vector2-Wert ist), macht sich der 2:2-Split wirklich praktisch.
Um die Chance zu erhöhen, dass zwei Operationen in einer Unit ausgeführt werden können, optimiert der Treiber den Shader Code. Damit werden Shader-Befehle umsortiert, ohne den mathematischen Ausdruck zu ändern, um so oft wie möglich Befehle zu "kombinieren" (was nVidia "dual issue" nennt.) Übrigens arbeitet kein Chip den Shader-Assemblercode direkt ab, dieser wird vorher übersetzt. Das Ergebnis kann ebenfalls optimiert werden.
Im Endeffekt kann jede NV40-Pipe bis zu vier arithmetische Instruktionen mit ihren beiden Shader Units ausführen. Da wir 16 Pipes ingesamt haben, erreichen wir als maximale Gesamt-Chipleistung 16T+64M. Doch "dual issue" kann längst nicht immer genutzt werden, so dass die tatsächliche Leistung darunter liegen wird.
R300 kann seine Units auch splitten, ist dabei aber nicht so flexibel, und jede R300-Pipe hat gerade mal eine einzige Shader Unit. Andererseits: Die R300 Units können alle mathematischen Operationen ausführen, außerdem gibt es eine zusätzliche Unit alleine für Textur-Operationen, während vom NV40 die Unit Nummer 1 und Nummer 2 jeweils auf bestimmte Operationen limitiert sind. Doch ingesamt sollte eine NV40-Pipe stärker sein als eine des R300.
Wir nehmen an, dass nVidias aktuelle Treiberversion noch nicht das ganze Potenzial an "dual issue"-Optimierungen ausschöpft. Für Technik-Freaks werfen wir jetzt einen näheren Blick auf die Pipe. Falls kein Bedarf an Details besteht, empfehlen wir einfach zum nächsten Kapitel zu blättern.
Ein vollständigeres Bild der NV40-Pipe.
Links fügten wir die "Mini-ALUs" hinzu. Eine Mini-ALU ist auch eine FP32-Unit, aber auf einige einfache Skalierungen und bestimmte Additionen ("Bias") limitiert. Für DirectX8-Shader sind solche "Modifier" in der Pipe wichtig, damit volle Leistung gebracht wird. Mit einer guten Shader-Optimierung kann eine Mini-ALU aber auch bestimmte DirectX9 Pixelshader-Operationen "kostenlos" machen. (Da DX8-Leistung eher Füllraten-limitiert ist, liefert NV40 mit 16 TMUs vs. 8 TMUs in den Vorgängern "nur" ca. doppelte Power.)
Wo wir gerade bei "kostenlos" sind: FP16-NRM ist oft "frei". NRM ist eine Instruktion (eigentlich ein Makro) um einen Vektor zu normalisieren (das heißt, seine Länge auf 1 zu setzen.) Das ist die einzige NV40-Instruktion, wo FP16 schneller ist als FP32. Sogar FX12 (ein Fixpoint-Format für DirectX8-Shader) ist nicht mehr schneller als FP32. Beim NV30 und NV35 waren FX12-Berechnungen noch sehr viel schneller als die gleiche Rechnung mit Floating Point.
Normalisierungs-Berechnungen werden oft bei Bumpmapping-Berechnungen genutzt. Bisher gibt es zwei Möglichkeiten, zu normalisieren: Entweder eine vorberechnete Cubemap zu nutzen, oder eine Dot-Operation gefolgt von RSQ und MUL. Gut, dass NRM_PP ("PP" steht für "partial precision", FP16) jetzt so schnell ist. Es wäre schöner, wenn ein full precision NRM ebenso schnell wäre.
Wenn es um die "Real World Performance" geht, bleibt der NV40 mit FP16 insgesamt schneller. Das kleinere FP-Format braucht weniger Bandbreite und weniger Platz im Register-File, so dass das File mehr Register halten kann.
NV35-Pipes können zumindestens zwei Dot-Operationen pro Takt ausführen. NV40 ist auf eine begrenzt, weil Shader Unit 1 zwar multiplizieren, aber nicht addieren kann. nVidia meint, ihre Shader-Analyse zeige dass in den meisten Fällen keine zwei ADDs oder DOTs gebraucht werden, so dass sie das nicht im NV40 einbauten.
Letztlich ist der NV40 weniger "statisch" als man vielleicht denken mag. Wenn Shader Unit 1 eine Textur-Operation ausführt, blockiert das eigentlich den Arithmetikteil. Aber hin und wieder fällt mindestens noch eine zusätzliche skalare Instruktion im gleichen Takt ab. Außerdem sieht es so aus, als enthielten die TMUs noch Logik für Skalierungen. Das kann die Shader-Units entlasten. Aber nochmals, unsere Beschreibungen und Bilder sollten nicht als Wiedergabe der tatsächlichen Pipeline, wie sie als Hardware-Aufbau aussieht, verstanden werden. Vielleicht gibt es gar keine zwei Shader Units, dafür eine große. Das wissen wir nicht, unser Ziel ist zu erläutern, was eine einzelne Pipeline pro Takt machen kann.
Obwohl eine NV40-Pipe weniger Rohpower hat als NV35-Pipes, schaffte es nVidia doch, die Effizienz erheblich zu steigern. Anders gesagt, wegen der großen Anzahl der Pipes ist die GPU dann sehr schnell. nVidia versprach, dass es kein hand-optimiertes Shader-Replacement mehr für Benchmarks geben würde. Solche "Optimierungen" seien nicht länger erforderlich.