-
QUERVERWEIS AUF VERWANDTE ANMELDUNGEN
-
Diese Anmeldung nimmt die Priorität der US-Provisional-Patentanmeldung mit dem Aktenzeichen 61/556,782, welche am 7. November 2011 eingereicht wurde, sowie die Priorität der US-Patentanmeldung mit dem Aktenzeichen 13/659,802, welche am 24. Oktober 2012 eingereicht wurde, in Anspruch. Jede dieser Anmeldungen wird hiermit durch Bezugnahme hierin aufgenommen.
-
HINTERGRUND DER ERFINDUNG
-
Gebiet der Erfindung
-
Die vorliegende Erfindung bezieht sich im Allgemeinen auf Grafikverarbeitungs-(GPU)-Rechencompiler (engl. „GPU computing compilers”) und spezifischer auf eine Technik zur inter-prozeduralen (engl. „inter-procedural”) Speicheradressenraumoptimierung (engl. „memory address space optimization”) in einem GPU-Rechencompiler.
-
Beschreibung des verwandten Standes der Technik
-
Graphikverarbeitungseinheiten (GPUs) sind mit der Zeit so entwickelt worden, dass sie zusätzlich zu graphikorientierten Operationen eine Vielzahl von Operationen unterstützen. Eine moderne GPU mag in der Tat dazu fähig sein, arbiträre Programmbefehle auszuführen. Eine solche GPU weist typischerweise einen Compiler auf, der Programmbefehle zur Ausführung auf einem oder mehreren Verarbeitungskernen kompiliert, die innerhalb der GPU enthalten sind. Jeder solche Kern mag einen bestimmten Ausführungsthread parallel zu anderen Verarbeitungskernen ausführen, die Ausführungsthreads ausführen.
-
Ein gegebener Kern innerhalb einer GPU mag an einen lokalen Speicherraum gekoppelt sein, welcher lokale Speicherraum für die GPU für Speicherzugriffsoperationen zur Verfügung steht, wenn sie einen Thread ausführt. Jeder Kern mag auch an einen gemeinsamen (engl. „shared”) Speicherraum gekoppelt sein, an welchen Speicherraum auch ein oder mehrere andere Kerne gekoppelt sein mögen. Mit dieser Konfiguration mögen mehrere Kerne Daten durch den gemeinsamen Speicherraum gemeinsam nutzen. Die Kerne innerhalb der GPU mögen auch an einen globalen Speicherraum gekoppelt sein, welcher für alle Verarbeitungskerne und gegebenenfalls für andere Verarbeitungseinheiten neben der GPU selbst zugriffbar ist.
-
Die oben beschriebene Konfiguration von mehreren verschidenen Speicherräumen wird in der Technik als eine „nicht uniforme Speicherarchitektur” bezeichnet. Eine nicht uniforme Speicherarchitektur weist im Allgemeinen mehrere verschiedene Speicherräume auf, in denen Daten residieren mögen. Ein Programm, das zum Ausführen auf einer GPU vorgesehen ist, mag auf Daten zugreifen, die in jeglichem oder allem der verschiedenen Speicherräumen in der nicht uniformen Speicherarchitektur residieren.
-
Verschiedene Speicherzugriffsoperationen mögen innerhalb eines solches Programms spezifiziert sein, wie zum Beispiel Lade/Speicher-Operationen (engl. „load/store operations”) oder elementare (engl. „atomic”) Operationen, wobei jede von diesen auf eine unterschiedliche Adresse abzielt. Eine gegebene Speicherzugriffsoperation, die auf eine gegebene Speicheradresse abzielt, mag aber keinen bestimmten Speicherraum spezifizieren. Bei konventionellen Lösungsansätzen liest die GPU, die das Programm ausführt, typischerweise während der Laufzeit (engl. „run time”) ein Tag (engl. „tag”), das mit der Adresse assoziiert ist und den bestimmten Speicherraum angibt, in welchem die Speicherzugriffsoperation ausgeführt werden soll. Ein Tag wird für jede Adresse benötigt, weil zwei verschiedene Variable zum Beispiel beide an der gleichen Adresse innerhalb unterschiedlicher Speicherräume residieren mögen. Ohne ein solches Tag wären die zwei Variable basierend auf den Adressen allein nicht zu unterscheiden sein.
-
Es ist aus zwei Gründen problematisch, sich auf dem oben beschriebenen Taggen-Ansatz (engl. „tagging approach”) zu verlassen. Erstens ist das Lesen eines Tags für jede Speicherzugriffsoperation eine teure Operation und verschwendet GPU-Ressourcen. Zweitens wird der GPU-Compiler daran gehindert, Programmcodeoptimierungen, einschließlich eines Neuordnens des Speicherzugriffs (engl. „memory access re-ordering”) oder einer Aliasanalyse, vor der Laufzeit durchzuführen, weil Variable, die die gleiche Adresse haben, bis zur Laufzeit nicht zu unterscheiden sind.
-
Folglich ist das, was in der Technik benötigt wird, eine effizientere Technik zum Kompilieren von GPU-Programmbefehlen.
-
ZUSAMMENFASSUNG DER ERFINDUNG
-
Eine Ausführungsform der vorliegenden Erfindung legt ein computerimplementiertes Verfahren zur Optimierung von Programmcode dar, der zur Ausführung auf einer Parallelverarbeitungseinheit (PPU), welche eine nicht uniforme Speicherarchitektur aufweist, kompiliert werden kann, das Verfahren aufweisend ein Identifizieren einer ersten Speicherzugriffsoperation, die mit einem ersten Zeiger assoziiert ist, wobei die erste Speicherzugriffsoperation auf einen generischen Speicherraum abzielt, ein Aszendieren (engl. „ascending”) einer Def-Use-Kette (engl. „use-definition chain”), die sich auf den ersten Zeiger bezieht, ein Hinzufügen des ersten Zeigers zu einem Vektor, nachdem es festgestellt wurde, dass der erste Zeiger von einem spezifischen Speicherraum in der nicht uniformen Speicherarchitektur abgeleitet (engl. „derived”) ist, und ein Bewirken, dass die erste Speicherzugriffsoperation auf den spezifischen Speicherraum abzielt, durch Modifizieren zumindest eines Abschnitts des Programmcodes.
-
Ein Vorteil der offenbarten Technik ist, dass eine Grafikverarbeitungseinheit nicht alle generischen Speicherzugriffsoperation während der Laufzeit auflösen (engl. „resolve”) muss, wodurch Ressourcen gespart werden und die Ausführung der Anwendung beschleunigt wird. Die Grafikverarbeitungseinheit ist des Weiteren dazu befähigt (engl. „enabled”), zusätzliche Programmcodeoptimierungen mit dem Programmcode der Anwendung durchzuführen, einschließlich eines Neuordnen des Speicherzugriffs und einer Aliasanalyse, was die Ausführung des Programmcodes weiter beschleunigt.
-
KURZE BESCHREIBUNG DER ZEICHNUNGEN
-
So dass die Art und Weise, in der die oben angeführten Merkmale der vorliegenden Erfindung im Detail verstanden werden kann, mag eine detailliertere Beschreibung der oben kurz zusammengefassten Erfindung durch Bezugnahme auf Ausführungsformen gehabt haben, von denen einige in der angehängten Zeichnungen dargestellt sind. Es muss aber bemerkt werden, dass die angehängten Zeichnungen nur typische Ausführungsformen der Erfindung illustrieren und somit nicht als den Umfang der Erfindung beschränkend angesehen werden dürfen, da die Erfindung andere gleich effektive Ausführungsformen zulassen mag.
-
1 ist ein Blockdiagramm, das ein Computersystem darstellt, das zum Implementieren eines oder mehrerer Aspekte der vorliegenden Erfindung konfiguriert ist;
-
2 ist ein Blockdiagramm von einem Parallelverarbeitungssubsystem für das Computersystem von 1, gemäß einer Ausführungsform der vorliegenden Erfindung;
-
3 zeigt einen Erstellungsprozess (engl. „build process”), der zum Kompilieren einer Coprozessor-geeigneten Anwendung (engl. „co-processor enabled application”) verwendet wird, gemäß einer Ausführungsform der vorliegenden Erfindung;
-
4 ist ein Flussdiagramm von Verfahrensschritten zur Optimierung von Speicherzugriffsoperationen, gemäß einer Ausführungsform der vorliegenden Erfindung;
-
5 ist ein Flussdiagramm von Verfahrensschritten zur Verlagerung (engl. „transferring”) konstanter Variable nach einem globalen Speicherraum, gemäß einer Ausführungsform der vorliegenden Erfindung; und
-
6 legt ein Beispiel eines Pseudocodes dar, um die Operation eines Geräte-Compiler-und-Linker (engl. „device compiler and linker”) zu illustrieren, gemäß einer Ausführungsform der vorliegenden Erfindung.
-
DETAILLIERTE BESCHREIBUNG
-
In der folgenden Beschreibung werden zahlreiche spezifische Details dargelegt, um ein eingehenderes Verständnis der vorliegenden Erfindung bereitzustellen. Es wird aber für einen Fachmann offenkundig sein, dass die vorliegende Erfindung auch ohne ein oder mehrere von diesen spezifischen Details ausgeübt werden kann.
-
Systemübersicht
-
1 ist ein Blockdiagramm, das ein Computersystem 100 zeigt, das zum Implementieren eines oder mehrerer Aspekte der vorliegenden Erfindung konfiguriert ist. Das Computersystem 100 weist eine zentrale Verarbeitungseinheit (engl. „central processing unit”) (CPU) 102 und einen Systemspeicher 104 auf, die über einen Verbindungspfad (engl. „interconnection path”), der eine Speicherbrücke 105 aufweisen mag, miteinander in Verbindung stehen bzw. kommunizieren. Der Systemspeicher 104 enthält ein Abbild eines Operativsystems 130, einen Treiber 103 und eine Coprozessor-geeignete Anwendung 134. Das Operativsystem 130 stellt detaillierte Befehle zum Managen und Koordinieren der Operation des Computersystems 100 bereit. Der Treiber 103 stellt detaillierte Befehle zum Managen und Koordinieren der Operation vom Parallelverarbeitungssubsystem 112 und einem oder mehreren darin residierenden Parallelverarbeitungseinheiten (PPUs) bereit, wie es unten in Verbindung mit der 2 detaillierter beschrieben wird. Der Treiber 103 stellt auch Kompilierungsmittel zum Erzeugen von Maschinencode bereit, der für solche PPUs spezifisch optimiert ist, wie es unten in Verbindung mit den 3–6 detaillierter beschrieben wird. Die Coprozessor-geeignete Anwendung 134 enthält Befehle, die auf der CPU 102 und den PPUs ausgeführt werden können, wobei diese Befehle in einem abstrakten Format implementiert sind, wie zum Beispiel virtuellem Assembler (engl. „virtual assembly”), und zu Maschinencode für die PPUs innerhalb des Verarbeitungssubsystem 112 mappt. Der Maschinencode für diese PPUs mag im Systemspeicher 104 oder in einem Speicher, der an die PPUs gekoppelt ist, gespeichert sein.
-
In einer Ausführungsform stellt die Coprozessor-geeignete Anwendung 134 CUDATM-Code dar, der Programmbefehle enthält, die für Ausführung auf dem Parallelverarbeitungssystem 112 bestimmt sind. Im Kontext der vorliegenden Beschreibung mag der Begriff „Anwendung” oder „Programm” auf jeglichen Computercode, jegliche Befehle und/oder Funktionen hinweisen, die unter Verwendung eines Prozessors ausgeführt werden können. In verschiedenen Ausführungsformen mag die Coprozessor-geeignete Anwendung 134 zum Beispiel C-Code, C++-Code usw. enthalten. In einer Ausführungsform mag die Coprozessor-geeignete Anwendung 134 eine Programmierspracheerweiterung einer Computersprache enthalten (zum Beispiel C, C++ usw.).
-
Die Speicherbrücke 105, die zum Beispiel ein Northbridge-Chip sein mag, ist über einen Bus oder einen anderen Kommunikationspfad 106 (zum Beispiel einen HyperTransport-Link) mit einer Input/Output-(I/O)-Brücke 107 verbunden. Die I/O-Brücke 107, welche zum Beispiel ein Southbridge-Chip sein mag, erhält User-Input von einer oder mehreren User-Input-Vorrichtungen 108 (zum Beispiel Tastatur, Maus) und leitet den Input über den Kommunikationspfad 106 und die Speicherbrücke 105 an die CPU 102 weiter. Ein Parallelverarbeitungssubsystem 112 ist über einen Bus oder einen zweiten Kommunikationspfad 113 (zum Beispiel einen „Peripheral Component Interconnect Express” (PCIe), einen beschleunigten Grafikport (engl. „Accelerated Graphics Port”) (AGP), oder einen HyperTransport-Link) an die Speicherbrücke 105 gekoppelt; in einer Ausführungsform ist das Parallelverarbeitungssubsystem 112 ein Grafiksubsystem, das Pixel zu einer Displayvorrichtung 110 liefert, die jede konventionelle Kathodenstrahlröhre, Flüssigkristalldisplay, Lichtemittierende-Diode-Display oder ähnliches sein mag. Eine Systemdisk 114 ist auch mit der I/O-Brücke 107 verbunden und mag dazu konfiguriert sein, Inhalt und Anwendungen und Daten zu speichern, so dass diese von der CPU 102 und dem Parallelverarbeitungssubsystem 112 verwendet werden können. Die Systemdisk 114 stellt nicht flüchtigen Speicher für Anwendungen und Daten bereit und mag feste oder lösbare Festplattenlaufwerke, Flashspeichervorrichtungen und Compact-Disk-(CD)-Festspeicher (ROM), Digital-Video-Disk-(DVD)-ROM, Blu-Ray, High-Definition-(HD)-DVD oder andere magnetischen, optischen oder Festkörper-Speichervorrichtungen enthalten.
-
Ein Switch 116 stellt Verbindungen zwischen der I/O-Brücke 107 und anderen Bauteilen bereit, wie zum Beispiel einem Netzwerkadapter 118 und verschiedenen Erweiterungskarten (engl. „add-in cards”) 120 und 121. Andere (nicht explizit dargestellte) Bauteile, einschließlich Universal-Serial-Bus (USB) oder anderer Portanschlüsse (engl. „port connections”), CD-Laufwerke, DVD-Laufwerke, Filmaufzeichnungsvorrichtungen und ähnliches, mögen auch mit der I/O-Brücke 107 verbunden sein. Die verschiedenen Verbindungspfade, die in 1 gezeigt sind, einschließlich der spezifisch benannten Kommunikationspfade 106 und 113, mögen unter Verwendung von jeglichen geeigneten Protokollen, wie zum Beispiel PCIe, AGP, HyperTransport oder jedem anderen Bus oder Punkt-zu-Punkt-Kommunikationsprotokoll(en) (engl. „Point-to-Point Communication Protocol(s)”) implementiert sein, und Verbindungen zwischen verschiedenen Vorrichtungen mögen verschiedene Protokolle benutzen, wie es aus dem Stand der Technik bekannt ist.
-
Das Parallelverarbeitungssubsystem 112 weist in einer Ausführungsform Schaltkreise auf, die für Grafik- und Videoverarbeitung optimiert sind, einschließlich zum Beispiel Videoausgabeschaltkreise, und stellt eine Grafikverarbeitungseinheit (GPU) dar. In einer anderen Ausführungsform weist das Parallelverarbeitungssubsystem 112 Schaltkreise auf, die für Universalverarbeitung (engl. „general purpose processing”) optimiert sind, während die unterliegende rechnerische Architektur aufrechterhalten wird (wie es hierin detaillierter beschrieben wird). In noch einer anderen Ausführungsform mag das Parallelverarbeitungssubsystem 112 mit einem oder mehreren anderen Systemelementen in einem einzigen Subsystem integriert sein, wie zum Beispiel durch Zusammenführen der Speicherbrücke 105, der CPU 102 und der I/O-Brücke 107, um ein System-auf-Chip (engl. „system an chip”) (SoC) zu bilden.
-
Es wird verstanden werden, dass das hierin gezeigte System illustrativ ist und dass Variationen und Modifikationen möglich sind. Die Verbindungstopologie, einschließlich der Anzahl und Anordnung von Brücken, der Anzahl von CPUs 102 und der Anzahl von Parallelverarbeitungssubsystemen 112, mag wie gewünscht variiert werden. In einigen Ausführungsformen ist der Systemspeicher 104 zum Beispiel direkt mit der CPU 102 verbunden, statt durch eine Brücke, und andere Vorrichtungen kommunizieren über die Speicherbrücke 105 und die CPU 102 mit dem Systemspeicher 104. In anderen alternativen Topologien ist das Parallelverarbeitungssubsystem 112 mit der I/O-Brücke 107 oder direkt mit der CPU 102 verbunden, statt mit der Speicherbrücke 105. In noch anderen Ausführungsformen mögen die I/O-Brücke 107 und Speicherbrücke 105 in einem einzigen Chip integriert sein statt als eine oder mehrere diskrete Vorrichtungen zu existieren. Große Ausführungsformen mögen zwei oder mehr CPUs 102 und zwei oder mehr Parallelverarbeitungssubsysteme 112 aufweisen. Die jeweiligen hierin gezeigten Bauteile sind optional; zum Beispiel mag jede Anzahl von Erweiterungskarten oder Peripheriegeräten unterstützt werden. In einigen Ausführungsformen ist der Switch 116 entfernt und der Netzwerkadapter 118 und die Erweiterungskarten 120, 121 sind direkt mit der I/O-Brücke 107 verbunden.
-
2 zeigt ein Parallelverarbeitungssubsystem 112 gemäß einer Ausführungsform der vorliegenden Erfindung. Das Parallelverarbeitungssubsystem 112 weist, wie gezeigt, eine oder mehr Parallelverarbeitungseinheiten (engl. „Parallel Processing Units”) (PPUs) 202 auf, wobei jede von denen an einen lokalen Parallelverarbeitungs-(PP)-Speicher 204 gekoppelt ist. Im Allgemeinen weist ein Parallelverarbeitungssubsystem eine Anzahl U von PPUs auf, wobei U größer oder gleich 1 ist. (Hierin werden mehrere Instanzen ähnlicher Objekte mit Bezugszeichen, die das Objekt identifizieren, und Ziffern in Klammern, die, wenn nötig, die Instanz identifizieren, gekennzeichnet.) Die PPUs 202 und die Parallelverarbeitungsspeicher 204 mögen unter Verwendung einer oder mehrerer integrierten Schaltungsvorrichtungen implementiert werden, wie zum Beispiel programmierbare Prozessoren, anwendungsspezifische integrierte Schaltungen (engl. „Application Specific Integrated Circuits”) (ASICs) oder Speichervorrichtungen, oder in jeder anderen technisch realisierbaren Art und Weise.
-
In einigen Ausführungsformen sind, wieder mit Bezug auf sowohl 1 als auch auf 2, einige oder alle der PPUs 202 in dem Parallelverarbeitungssubsystem 112 Grafikprozessoren mit Rendering-Pipelines, die dazu konfiguriert werden können, verschiedene Operationen in Bezug auf das Erzeugen von Pixeldaten aus Grafikdaten, die von der CPU 102 und/oder dem Systemspeicher 104 über die Speicherbrücke 105 und den zweiten Kommunikationspfad 113 bereitgestellt werden, auszuführen, mit lokalem Parallelverarbeitungsspeicher 204 (der als Grafikspeicher einschließlich, zum Beispiel, eines konventionellen Framepuffers benutzt werden kann) zu interagieren, um Pixeldaten zu speichern und zu aktualisieren, Pixeldaten an die Displayvorrichtung 110 zu übermitteln, und ähnliches. In einigen Ausführungsformen mag das Parallelverarbeitungssubsystem 112 eine oder mehrere PPUs 202 aufweisen, die als Grafikprozessoren arbeiten, und eine oder mehrere PPUs 202, die für Universalberechnungen (engl. „general-purpose computations”) benutzt werden. Die PPUs mögen identisch oder unterschiedlich sein, und jede PPU mag eine dedizierte(n) Parallelverarbeitungsspeichervorrichtung(en) oder keine dedizierte(n) Parallelverarbeitungsspeichervorrichtung(en) aufweisen. Eine oder mehrere PPUs 202 in dem Parallelverarbeitungssubsystem 112 mag bzw. mögen Daten an eine Displayvorrichtung 110 ausgeben oder jede PPU 202 in dem Parallelverarbeitungssubsystem 112 mag Daten an eine oder mehrere Displayvorrichtungen 110 ausgeben.
-
Im Betrieb ist die CPU 102 der Masterprozessor des Computersystems 100, welcher den Betrieb anderer Systembauteile steuert und koordiniert. Die CPU 102 erteilt insbesondere Befehle, die den Betrieb der PPUs 202 steuern. In einigen Ausführungsformen schreibt die CPU 102 einen Befehlsstrom für jede PPU 202 in eine (weder in 1 noch in 2 explizit gezeigte) Datenstruktur, die sich im Systemspeicher 104, Parallelverarbeitungsspeicher 204 oder in einer anderen Speicherstelle befinden mag, die für sowohl die CPU 102 als auch die PPU 202 zugreifbar ist. Ein Zeiger auf jede Datenstruktur wird in einen Stoßpuffer (engl. „push puffer”) geschrieben, um Verarbeitung des Befehlsstroms in der Datenstruktur zu initiieren. Die PPU 202 liest Befehlsströme aus einem oder mehreren Stoßpuffern aus und führt dann Befehle asynchron relativ zu dem Betrieb der CPU 102 aus. Ausführungsprioritäten mögen für jeden Stoßpuffer von einem Anwendungsprogramm über Gerätetreiber 103 festgelegt werden, um das Scheduling der verschiedenen Stoßpuffer zu steuern.
-
Jede PPU 202 weist eine I/O-(Input/Output)-Einheit 205 auf, die mit dem restlichen Computersystem 100 über Kommunikationspfad 113 kommuniziert, der mit der Speicherbrücke 105 (oder in einer alternativen Ausführungsform direkt mit der CPU 102) in Verbindung steht. Die Verbindung der PPU 202 an das restliche Computersystem 100 mag auch variiert werden. In einigen Ausführungsformen ist das Parallelverarbeitungssubsystem 112 als eine Erweiterungskarte implementiert, die in einen Erweiterungsslot (engl. „expansion slot”) des Computersystems 100 eingebracht werden kann. In anderen Ausführungsformen kann eine PPU 202 auf einem einzigen Chip mit einer Busbrücke, wie zum Beispiel Speicherbrücke 105 oder I/O-Brücke 107, integriert sein. In noch anderen Ausführungsformen mögen einige oder alle Elemente der PPU 202 auf einem einzigen Chip mit der CPU 102 integriert sein.
-
In einer Ausführungsform ist der Kommunikationspfad 113 ein PCIe-Anschluss (engl. „PCIe-link”), wie oben erwähnt, in welchem jeder PPU 202 dedizierte Spuren zugewiesen sind, wie es auf dem technischen Gebiet bekannt ist. Andere Kommunikationspfade mögen auch benutzt werden. Eine I/O-Einheit 205 erzeugt Pakete (oder andere Signale) für Transmission auf dem Kommunikationspfad 113 und empfängt auch alle ankommenden Pakete (oder anderen Signale) von dem Kommunikationspfad 113, wobei die ankommenden Pakete zu zweckmäßigen Bauteilen der PPU 202 geleitet werden. Befehle, die sich auf Bearbeitungstasks beziehen, mögen zum Beispiel zu einer Hostschnittstelle (engl. „host interface”) 206 geleitet werden, während Befehle, die sich auf Speichervorgänge (zum Beispiel Auslesen aus oder Schreiben auf den Parallelverarbeitungsspeicher 204) beziehen, zu einer Speicher-Kreuzschieneneinheit 210 geleitet werden mögen. Die Hostschnittstelle 206 liest jeden Stoßpuffer aus und gibt den Befehlsstrom, der in dem Stoßpuffer gespeichert ist, zu einem Frontend 212 aus.
-
Jede PPU 202 implementiert vorteilhafterweise eine in hohem Maße parallele Verarbeitungsarchitektur. Die PPU 202(0) weist, wie im Detail gezeigt, ein Verarbeitungscluster-Array (engl. „processing cluster array”) 230 auf, das eine Anzahl C von Allgemeinverarbeitungsclustern (engl. „general processing clusters”) (GPCs) 208 aufweist, wobei C ≥ 1. Jeder GPC 208 ist in der Lage, eine große Anzahl (zum Beispiel hunderte oder tausende) von Threads gleichzeitig auszuführen, wobei jeder Thread eine Instanz eines Programms ist. In verschiedenen Applikationen mögen unterschiedlichen GPCs 208 zur Verarbeitung unterschiedlicher Arten von Programmen oder zum Ausführen unterschiedlicher Arten von Berechnungen allokiert werden. Das Allokieren von GPCs 208 mag in Abhängigkeit von der Auslastung variieren, die für jede Art von Programm oder Berechnung entsteht.
-
Die GPCs 208 empfangen auszuführende Verarbeitungstasks von einer Arbeitsverteilungseinheit innerhalb einer Task/Arbeit-Einheit (engl. „task/work unit”) 207. Die Arbeitsverteilungseinheit empfängt Zeiger auf Verarbeitungstasks, die als Taskmetadaten (engl. „task metadata”) (TMD) kodiert und im Speicher gespeichert sind. Die Zeiger auf TMDs sind in den Befehlsstrom beinhaltet, der als ein Stoßpuffer gespeichert und mittels der Frontend-Einheit 212 von der Host-Schnittstelle 206 empfangen wird. Verarbeitungstasks, die als TMDs kodiert werden mögen, beinhalten Indices von zu verarbeitenden Daten sowie Zustandsparameter und Befehle, die definieren wie die Daten zu verarbeiten sind (zum Beispiel welches Programm auszuführen ist). Die Task/Arbeit-Einheit 207 empfängt Tasks von dem Frontend 212 und stellt sicher, dass die GPCs 208 zu einem gültigen Zustand konfiguriert sind, bevor die von jedem einzelnen der TMDs spezifizierte Verarbeitung eingeleitet wird. Eine Priorität mag für jede TMD, die zum Scheduling der Ausführung der Verarbeitungstasks benutzt wird, spezifiziert sein. Verarbeitungstasks können auch von dem Verarbeitungsclusterarray 230 erhalten werden. Die TMD können optional einen Parameter enthalten, der steuert, ob die TMD zu dem Kopf oder Ende von einer Liste von Verarbeitungstasks (oder Liste von Zeigern auf die Verarbeitungstasks) hinzugefügt wird, wodurch eine andere Stufe von der Steuerung der Priorität bereitgestellt wird.
-
Die Speicherschnittstelle 214 weist eine Anzahl D von Partitionseinheiten 215 auf, die jeweils direkt an einen Teil des Parallelverarbeitungsspeichers 204 gekoppelt sind, wobei D ≥ 1. Die Anzahl der Partitionseinheiten 215 ist, wie gezeigt, generell gleich der Anzahl von dynamischem RAM (DRAM) 220. In anderen Ausführungsformen mag die Anzahl der Partitionseinheiten 215 nicht gleich der Anzahl der Speichervorrichtungen sein. Durchschnittliche Fachleute werden verstehen, dass DRAM 220 durch andere geeignete Speichervorrichtungen ersetzt werden mag und von einer generell konventionellen Bauform sein kann. Eine detaillierte Beschreibung wird deswegen weggelassen. Render-Ziele, wie zum Beispiel Puffer- oder Strukturpläne, mögen quer über die DRAMs 220 gespeichert werden, was den Partitionseinheiten 215 ermöglicht, Teile von jedem Render-Ziel parallel zu schreiben, um die vorhandene Bandbreite des Parallelverarbeitungsspeichers 204 effizient zu nutzen.
-
Jeder der GPCs 208 mag Daten verarbeiten, die in irgendeinen der DRAMs 220 innerhalb des Parallelverarbeitungsspeichers 204 zu schreiben sind. Die Kreuzschieneneinheit 210 ist dazu konfiguriert, den Output jedes GPC 208 an den Input einer jeden Partitionseinheit 215 oder an einen anderen GPC 208 für weitere Verarbeitung zu leiten. Die GPCs 208 kommunizieren mit der Speicherschnittstelle 214 durch die Kreuzschieneneinheit 210, um aus bzw. in verschiedenen externen Speichervorrichtungen auszulesen bzw. zu schreiben. In einer Ausführungsform hat die Kreuzschieneneinheit 210 sowohl eine Verbindung zu der Speicherschnittstelle 214, um mit der I/O-Einheit 205 zu kommunizieren, als auch eine Verbindung zu dem lokalen Parallelverarbeitungsspeicher 204, wodurch es den Verarbeitungskernen innerhalb der verschiedenen GPCs 208 ermöglicht werden, mit dem Systemspeicher 104 oder einem anderen Speicher, der kein lokaler Teil der PPU 202 ist, zu kommunizieren. In der in 2 gezeigten Ausführungsform ist die Kreuzschieneneinheit 210 direkt mit der I/O-Einheit 205 verbunden. Die Kreuzschieneneinheit 210 mag virtuelle Kanäle benutzen, um Datenverkehrsströme zwischen den GPCs 208 und den Partitionseinheiten 215 zu separieren.
-
Wie erwähnt können die GPCs 208 zum Ausführen von Verarbeitungstasks, die sich auf eine umfangreiche Vielfalt von Applikationen beziehen, programmiert werden, einschließlich, aber nicht begrenzt auf, linearer und nicht-linearer Datentransformationen, Filtern von Video- und/oder Audiodaten, Modellierungsvorgänge (zum Beispiel der Anwendung von physikalischen Gesetzen zum Bestimmen von Position, Geschwindigkeit und anderen Eigenschaften von Objekten), Bild-Rendering-Vorgängen (zum Beispiel Mosaikshader-, Scheitelshader-, Geometrieshader- und/oder Pixel-Shaderprogramme (engl. „tesselation shader, vertex shader, geometry shader, and/or pixel shader programs”)), usw. Die PPUs 202 mögen Daten von dem Systemspeicher 104 und/oder den lokalen Parallelverarbeitungsspeichern 204 in einen internen (auf-dem-Chip) Speicher hinein übertragen, die Daten verarbeiten und die Ergebnisdaten zurück in den Systemspeicher 104 und/oder die lokalen Parallelverarbeitungsspeicher 204 schreiben, wo auf solche Daten von anderen Systembauteilen, einschließlich CPU 102 oder anderer Parallelverarbeitungssubsysteme 112, zugegriffen werden kann.
-
Eine PPU 202 mag mit jeder Menge lokaler Parallelverarbeitungsspeicher 204, einschließlich keiner lokalen Speicher, ausgestattet sein, und mag lokalen Speicher und Systemspeicher in jeder beliebigen Kombination benutzen. Eine PPU 202 kann zum Beispiel ein Grafikprozessor in einer Ausführungsform mit „unified memory architecture” (UMA) sein. In solchen Ausführungsformen würde wenig oder kein dedizierter Grafik-(Parallelverarbeitungs-)Speicher bereitgestellt werden, und die PPU 202 würde ausschließlich oder fast ausschließlich den Systemspeicher benutzen. In UMA-Ausführungsformen mag eine PPU 202 in einem Brückenchip oder Prozessorchip integriert sein oder als ein diskreter Chip mit einem Hochgeschwindigkeitsanschluss (beispielsweise PCI-Express), der die PPU 202 über einen Brückenchip oder ein anderes Kommunikationsmittel mit dem Systemspeicher verbindet, bereitgestellt werden. In der Ausführungsform der Erfindung, welche Ausführungsform in Zusammenhang mit den 3–6 beschrieben wird, ist jede PPU 202 mit einer nicht gleichmäßigen (engl. „non-uniform”) Speicherarchitektur implementiert und jede solche PPU 202 mag folglich Zugriff auf mehrere verschiedenen Speicherräume haben, wie es von der Coprozessor-geeigneten Anwendung 134 angewiesen wird.
-
Wie oben erwähnt, kann eine beliebige Anzahl von PPUs 202 in einem Parallelverarbeitungssubsystem 112 enthalten sein. Mehrere PPUs 202 können zum Beispiel auf einer einzigen Erweiterungskarte bereitgestellt werden oder mehrere Erweiterungskarten können mit dem Kommunikationspfad 113 verbunden werden oder eine oder mehrere der PPUs 202 können in einem Brückenchip integriert werden. Die PPUs 202 in einem Mehrfach-PPU-System mögen gleich oder unterschiedlich voneinander sein. Unterschiedliche PPUs 202 mögen zum Beispiel eine jeweils unterschiedliche Anzahl von Prozessorkernen, unterschiedliche Mengen von lokalem Parallelverarbeitungsspeicher usw. aufweisen. Wenn mehrere PPUs 202 vorhanden sind, mögen diese PPUs parallel betrieben werden, um Daten mit einem größeren Durchsatz, als es mit einer einzigen PPU 202 möglich ist, zu verarbeiten. Systeme, die eine oder mehrere PPUs 202 aufweisen, mögen in einer Vielfalt von Konfigurationen und Formfaktoren implementiert werden, einschließlich Desktop-, Laptop- oder handgeführter Rechner, Server, Arbeitsstationen (engl. „workstations”), Spielkonsolen, eingebetteter Systeme und ähnliches.
-
Wie erwähnt, in der Ausführungsform der Erfindung, die in Zusammenhang mit den 3–6 beschriebenen wurde, ist jede PPU 202 mit einer nicht uniformen Speicherarchitektur implementiert. Jede solche PPU 202 mag folglich Zugriff auf mehrere verschiedene Speicherräume haben, wie zum Beispiel Systemspeicher 104 oder PP-Speicher 204, unter anderem, wie es von der Coprozessor-geeigneten Anwendung 134 angewiesen wird. Eine Compiler-und-Linker-Anwendung, die vom Gerätetreiber 103 abgeleitet ist, ist dazu konfiguriert, Programmcode zu optimieren und kompilieren, um die Coprozessor-geeignete Anwendung 134 zu erzeugen. Dieser Programmcode mag anfangs verschiedene Speicherzugriffsoperationen enthalten, wie zum Beispiel Lade/Speicher-Operationen oder elementare Operationen, die keinen spezifischen Speicherraum definieren mögen, mit welchem die Speicherzugriffsoperationen auszuführen sind. Solche Speicherzugriffsoperationen werden hierin als „generische Speicherzugriffsoperationen” bezeichnet. Um den Programmcode zu optimieren, ist die Compiler-und-Linker-Anwendung dazu konfiguriert, dieser Programmcode nach Bedarf zu modifizieren, um generische Speicherzugriffsoperationen in spezifische Speicherzugriffsoperationen aufzulösen, die auf einen bestimmten Speicherraum abzielen, wie es unten in Zusammenhang mit den 3–6 detaillierter beschrieben wird.
-
3 zeigt den Erstellungsprozess, der zum Kompilieren der Coprozessor-geeigneten Anwendung 134 von 1 verwendet wird, gemäß einer Ausführungsform der vorliegenden Erfindung. Der Programmcode 310 enthält Host-Quellcode 312 und Geräte-Quellcode 314. Der Host-Quellcode 312 enthält Programmbefehle, die dafür vorgesehen sind, auf einem Host, wie zum Beispiel einem ×86-basierten persönlichen Rechner (PC) oder Server, ausgeführt zu werden. Die Programmbefehle im Quellcode 312 mögen Aufrufe zu Funktionen enthalten, die in dem Geräte-Quellcode 314 definiert sind. Jeder technisch geeignete Mechanismus mag verwendet werden, um zu spezifizieren, welche Funktionen als Geräte-Quellcode 314 gekennzeichnet sind.
-
Der Host-Quellcode 312 wird vorverarbeitet, kompiliert und eingebunden (engl. „linked”) von einem Host-Compiler-und-Linker 322. Der Host-Compiler-und-Linker 322 erzeugt Hostmaschinencode 342, der innerhalb der Coprozessor-geeigneten Anwendung 134 gespeichert wird.
-
Der Geräte-Quellcode 314 wird vorverarbeitet, kompiliert und eingebunden von einem Geräte-Compiler-und-Linker 324. Diese Kompilierungsoperation bildet eine Kompilierung erster Stufe von dem Geräte-Quellcode 314. Der Geräte-Compiler-und-Linker 324 erzeugt virtuellen Geräte-Assembler 346, der innerhalb eines Geräte-Codespeichers 350 gespeichert wird, welcher sich bei oder innerhalb der Coprozessor-geeigneten Anwendung 134 befindet. Ein Übersetzer 334 virtueller Befehle mag Geräte-Maschinencode 324 aus dem virtuellen Geräte-Assembler 346 erzeugen. Diese Kompilierungsoperation bildet eine Kompilierung zweiter Stufe von dem Geräte-Quellcode 314. Der Übersetzer 334 virtueller Befehle mag mehr als eine Version von Geräte-Maschinencode 344 erzeugen, basierend auf der Verfügbarkeit von bekannten Architekturdefinitionen. Zum Beispiel mag der Übersetzer 334 virtueller Befehle eine erste Version vom Geräte-Maschinencode 344, die native 64-Bit arithmetische Befehle (die in der ersten Zielarchitektur zur Verfügung stehen) aufrufen, und eine zweite Version vom Geräte-Maschinencode 344 erzeugen, die 64-Bit arithmetische Befehle auf solchen Ziele emuliert, die keine native 64-Bit arithmetische Befehle enthalten.
-
Architekturinformation 348 kennzeichnet die tatsächliche Architekturversion, die zum Erzeugen des Geräte-Maschinencodes 344 verwendet wurde. Die tatsächliche Architekturversion definiert die Features, die in nativen Befehlen innerhalb eines tatsächlichen Ausführungsziels, wie zum Beispiel der PPU 202, implementiert sind. Die Architekturinformation 348 kennzeichnet auch die Version der virtuellen Architektur, die zum Erzeugen des virtuellen Geräte-Assemblers 346 verwendet wurde. Die virtuelle Architekturversion definiert die Features, die entweder als nativ oder leicht emulierbar zu sein angenommen werden, und die Features, die nicht zum Emulieren geeignet sind. Elementare (engl. „atomic”) Additionsoperationen sind zum Beispiel zum Emulieren auf der Befehlsebene nicht geeignet, obwohl sie auf der algorithmischen Ebene in bestimmten Fällen insgesamt vermieden werden mögen, und mögen folglich beeinflussen, welche Funktionen in der ersten Kompilierungsstufe kompiliert werden mögen.
-
Zusätzlich zu dem Geräte-Maschinencode 344 und virtuellen Geräte-Assembler 346 mag der Geräte-Codespeicher auch Architekturinformation 348 enthalten, die kennzeichnet, welche Architektur-Features angenommen wurde, wenn der Geräte-Maschinencode 344 und der virtuelle Geräte-Assembler 346 erzeugt wurden. Fachleute werden erkennen, dass die Funktionen, die innerhalb des Geräte-Maschinencodes 344 und virtuellen Assemblers 346 enthalten sind, Funktionen Wiederspiegeln (engl. „reflect”), die mit der tatsächlichen Architektur der PPU 202 assoziiert sind. Die Architekturinformation 348 stellt Kompatibilitätsinformation für den Geräte-Maschinencode 344 und Compilerhinweise für eine Kompilierungsoperation zweiter Stufe bereit, die zu irgendeinem Zeitpunkt, nachdem die Entwicklung der Coprozessor-geeigneten Anwendung 134 schon beendet wurde, von einem Gerätetreiber 103 ausgeführt werden mögen.
-
Inter-prozedurale Speicherraumoptimierung
-
Der Geräte-Compiler-und-Linker 324 ist auch dazu konfiguriert, verschiedene Optimierungsroutinen mit verschiedenen Prozeduren und/oder Funktionen innerhalb des Programmcodes 310 auszuführen. Wie erwähnt mag der Programmcode 310 anfangs generische Speicherzugriffsoperationen enthalten, die keinen bestimmten Speicherraum spezifizieren, und der Geräte-Compiler-und-Linker 324 ist dazu konfiguriert, den Programmcode derart zu modifizieren, dass die generischen Speicherzugriffsoperationen in solche Speicherzugriffsoperationen auflösen werden, die auf einen bestimmten Speicherraum abzielen. 4 beschreibt einen Ansatz zum Optimieren von Speicherzugriffsoperationen, 5 beschreibt einen Ansatz zum Verlagern konstanter Variable zum Residieren in einem globalen Speicherraum und 6 beschreibt ein beispielhaftes Szenario, in welchem die in Zusammenhang mit den 4 und 5 abgehandelten Ansätze vorteilhaft sein mögen.
-
4 ist ein Flussdiagram von Verfahrensschritten zum Optimieren von Speicherzugriffsoperationen, gemäß einer Ausführungsform der vorliegenden Erfindung. Obwohl die Verfahrensschritte im Zusammenhang mit den Systemen von den 1–2 beschrieben werden, werden Fachleute verstehen, dass jedes System, das konfiguriert ist zum Ausführen der Verfahrensschritte, in jeglicher Reihenfolge, in dem Umfang der vorliegenden Erfindung enthalten ist. Der Geräte-Compiler-und-Linker 324, der in 3 gezeigt ist, ist dazu konfiguriert, die Verfahrensschritte zu implementieren.
-
Wie gezeigt beginnt ein Verfahren 400 bei Schritt 402, wo der Geräte-Compiler-und-Linker 324 Speicherzugriffsoperationen innerhalb des Programmcodes 310 sammelt, die auf einen generischen Speicherraum abzielen. Die Speicherzugriffsoperationen mögen Lade/Speicher-Operationen oder elementare Operationen sein, wie zum Beispiel Zeiger-Bezugsaufhebung (engl. „pointer de-referencing”). Bei Schritt 404 aszendiert der Geräte-Compiler-und-Linker 324 für jede Speicherzugriffsoperation, die beim Schritt 402 gesammelt wurde, eine Def-Use-Kette, die für den Zeiger erzeugt wurde, der mit der Speicherzugriffsoperation assoziiert ist, um den spezifischen Speicherraum festzustellen, von dem der Zeiger abgeleitet ist. Der Geräte-Compiler-und-Linker 324 mag die Def-Use-Kette unter Verwendung verschiedener Techniken erzeugen, wie zum Beispiel Datenflussanalyse, um die Verwendung des Zeigers und jede frühere Definitionen, die den Zeiger einbinden, zu identifizieren. In einer Ausführungsform erzeugt der Geräte-Compiler-und-Linker 324 die Def-Use-Kette unter Verwendung von live Analyse-basierten Techniken.
-
Bei Schritt 406 fügt der Geräte-Compiler-und-Linker 324 jeden Zeiger, der von einem spezifischen Speicherraum (wie zum Beispiel globalem Speicher, lokalem Speicher, gemeinsamem Speicher, usw.) abgeleitet ist, zu einem Vektor hinzu. Bei Schritt 408 modifiziert der Geräte-Compiler-und-Linker 324, für jeden Zieger in dem im Schritt 406 erzeugten Vektor, die Speicherzugriffsoperation, die mit diesem Zeiger assoziiert ist, um auf den spezifischen Speicherraum abzuzielen, von welchem der Zeiger abgeleitet wurde. Ein bestimmter Zeiger p, der von globalem Speicher abgeleitet ist, mag zum Beispiel während einer Ladeoperation bezugsaufgehoben (engl. „de-referenced”) werden. Durch Implementieren des Verfahrens 400 könnte der Geräte-Compiler-und-Linker 324 die Zeiger-Bezugsaufhebung durch eine Ladeoperation ersetzen, die spezifisch auf globalen Speicher abzielt.
-
In einigen Situationen mag der Geräte-Compiler-und-Linker 324 nicht dazu fähig sein, das Verfahren 400 zu implementieren, um eine gegebene Speicherzugriffsoperation derart zu modifizieren, dass er auf einen spezifischen Speicherraum innerhalb des Programmcodes 310 abzielt. Eine solche Situation mag auftreten, wenn der Programmcode 310 einen Verzweigungsbefehl enthält. Da das Ergebnis eines Verzweigungsbefehls bis zur Laufzeit unbekannt ist, mögen Speicherzugriffsoperationen, die in Abhängigkeit von dem Ergebnis des Verzweigungsbefehls auf unterschiedliche Speicherräume abzielen, nicht in der oben beschriebenen Art und Weise modifizierbar sein. In einigen Fällen mögen diese Speicherzugriffsoperationen als generische Speicherzugriffsoperationen unberührt belassen und zur Laufzeit aufgelöst werden.
-
Speicherzugriffsoperationen auf einen Speicherraum, der für konstanten Variable reserviert ist, mögen aber zur Laufzeit nicht effektiv aufgelöst werden. Da konstanter Speicherraum typischerweise innerhalb eines ausschließlich lesbaren (engl. „read-only”) Speichers residiert, sind Speicherzugriffsoperationen, die mit konstantem Speicher assoziiert sind, fundamental unterschiedlich von anderen Speicherzugriffsoperationen und mögen als solche zur Laufzeit nicht auflösbar sein. Der Geräte-Compiler-und-Linker 324 ist folglich dazu konfiguriert, bestimmte konstante Variable und die assoziierten Speicherzugriffsoperationen innerhalb des Programmcodes 310 derart zu verlagern, dass sie jeweils in einem globalen Speicherraum residiert und auf diesen abzielt, wie es unten in Zusammenhang mit der 5 detaillierter diskutiert wird.
-
5 ist ein Blockdiagramm von Verfahrensschritten zur Verlagerung konstanter Variable, so dass diese in globalem Speicherraum residieren, gemäß einer Ausführungsform der vorliegenden Erfindung. Obwohl die Verfahrensschritte in Zusammenhang mit den Systemen der 1–2 beschrieben werden, werden Fachleute verstehen, dass jedes System, das zur Durchführung der Verfahrensschritte, in beliebiger Reihenfolge, konfiguriert ist, innerhalb des Umfangs der vorliegenden Erfindung ist. Der in 3 gezeigte Geräte-Compiler-und-Linker 324 ist dazu konfiguriert, die Verfahrensschritte zu implementieren.
-
Ein Verfahren 500 beginnt, wie gezeigt, bei Schritt 502, bei dem der Geräte-Compiler-und-Linker 324, für jede konstante Adresse im Programmcode 310, die Def-Use-Kette für die konstante Adresse aszendiert, bis eine Speicherzugriffsoperation erreicht wird. Der Geräte-Compiler-und-Linker 324 mag die Def-Use-Kette unter Verwendung von konventionellen Techniken erzeugen, wie zum Beispiel Datenflussanalyse, um die Deklaration der konstanten Adresse und jeder nachfolgenden Verwendungen zu identifizieren. In einer Ausführungsform erzeugt der Geräte-Compiler-und-Linker 324 die Def-Use-Kette unter Verwendung von live Analyse-basierten Techniken.
-
Bei Schritt 504 markiert der Geräte-Compiler-und-Linker 324, für jede Speicherzugriffsoperation, die im Schritt 502 erreicht wurde und mit einem bestimmten konstanten Adresse assoziiert ist, eine konstante Deklaration, die mit der konstanten Adresse assoziiert ist, als „muss verlagert werden” (engl. „must-transfer”), wenn die Speicherzugriffsoperation nicht auf einen spezifischen Speicherraum aufgelöst wurde.
-
Bei Schritt 506 erzeugt der Geräte-Compiler-und-Linker 324 eine Abhängigkeitsliste für jede Speicherzugriffsoperation. Bei Schritt 508 identifiziert der Geräte-Compiler-und-Linker 324 jegliche Abhängigkeitslisten, die konstante Adressen mit Deklarationen, die als „muss verlagert werden” markiert sind, enthalten. Bei Schritt 510 markiert der Geräte-Compiler-und-Linker 324 jegliche Speicherzugriffsoperationen, die mit den im Schritt 508 identifizierten Abhängigkeitslisten assoziiert sind, als „muss verlagert werden”. Bei Schritt 512 markiert der Geräte-Compiler-und-Linker 324 jegliche konstanten Deklarationen, die mit konstanten Adressen innerhalb der identifizierten Abhängigkeitslisten assoziiert sind, als „muss verlagert werden”. Bei Schritt 514 modifiziert der Geräte-Compiler-und-Linker 324 jede verlagerbare konstante Deklaration, um eine Stelle im globalen Speicherraum zu spezifizieren. Bei Schritt 516 modifiziert der Geräte-Compiler-und-Linker 324 jede verlagerbare Speicherzugriffsoperation, um auf globalen Speicher abzuzielen. Dann endet das Verfahren 500.
-
Durch Implementieren des Verfahrens 500 kann der Geräte-Compiler-und-Linker 324 konstante Variable verlagern, so dass diese in einem globalen Speicherraum residieren, in Situationen, wo Verzweigungsbefehle ansonsten Speicherzugriffsoperationen, die diese konstanten Variable einbinden, als generische Speicherzugriffsoperationen belassen wurden. Des Weiteren ist der Geräte-Compiler-und-Linker 324 auch dazu konfiguriert, jegliche konstante Variable und assoziierte Speicherzugriffsoperationen, die von früher verlagerten Variablen abhängig sind, zu verlagern, wodurch es gesichert wird, dass alle abhängigen konstanten Variable zusammen verlagert werden.
-
Die Verfahren 400 und 500, die oben im Zusammenhang mit den 4 und 5 jeweils beschrieben wurden, werden unten in Zusammenhang mit der 6 anhand eines Beispiels detaillierter dargestellt.
-
6 legt ein Pseudocode-Beispiel zur Illustration der Operation eines Geräte-Compiler-und-Linker dar, gemäß einer Ausführungsform der vorliegenden Erfindung. Der Pseudocode 600 enthält, wie gezeigt, die Pseudocodeblöcke 610, 620, 630 und 640. Der Pseudocodeblock 610 enthält zwei konstante Int-Deklarationen (engl. „constant int declarations”) für die Variable c1 und c2 und eine gemeinsame Int-Deklaration für die Variable s. Der Pseudocodeblock 620 enthält drei Zeigerzuordnungen p1, p2 und p4 zu Adressen von den Variablen c1, s und c2. Der Pseudocodeblock 630 enthält Verzweigungsbefehle 632 und 634, die jeweils die Zeiger p3 und p5 unterschiedlich zuordnen, in Abhängigkeit davon, welche Abzweigung zur Laufzeit gefolgt wird. Der Pseudocodeblock 640 enthält Speicherzugriffsoperationen, die die Daten, die bei den Zeigern p3, p5 und p1 gespeichert sind, jeweils zu den Variablen x, y und z setzen. Fachleute werden verstehen, dass der oben beschriebene Pseudocode 600 in einfacher Weise in einer Vielzahl von Programmiersprachen implementiert werden kann. In einer Ausführungsform mag der Pseudocode 600 in der CUDATM-Programmiersprache implementiert werden und mag einen Teil von dem Programmcode 310 oder den ganzen Programmcode 310 darstellen.
-
Die folgende Beschreibung stellt nur ein Beispiel von einem Geräte-Compiler-und-Linker 324 dar, der das Verfahren 400 ausführt, das oben in Zusammenhang mit der 4 beschrieben wurde. In diesem Beispiel identifiziert der Geräte-Compiler-und-Linker 324 erst die Speicherzugriffsoperationen innerhalb des Pseudocodeblocks 640, ähnlich dem Schritt 402 des Verfahrens 400. Diese Speicherzugriffsoperationen sind, wie gezeigt, mit den Zeigern p1, p3 und p5 assoziiert.
-
Der Geräte-Compiler-und-Linker 324 aszendiert dann die Def-Use-Kette von jeder solchen Speicherzugriffsoperation, ähnlich dem Schritt 404 des Verfahrens 400. In dem Pseudocode 600 aszendiert der Geräte-Compiler-und-Linker 324 die Def-Use-Kette von p3 dadurch, dass er jede Abzweigung des Verzweigungsbefehls 632 bis auf die Zeigerzuordnungen von p1 und p2 im Pseudocodeblock 620 hinauf folgt, und dann (engl. „tracing”) die Variable c1 und s zurück zu der Deklaration dieser Variable innerhalb des Pseudocodeblocks 610 verfolgt. In ähnlicher Weise aszendiert der Geräte-Compiler-und-Linker 324 die Def-Use-Kette von p5 dadurch, dass er jede Abzweigung des Verzweigungsbefehls 634 bis auf die Zeigerzuordnungen von p1 und p4 im Pseudocodeblock 620 hinauf folgt, und dann die Variable c1 und c2 zurück zu der Deklaration dieser Variable innerhalb des Pseudocodeblocks 610 verfolgt. Der Geräte-Compiler-und-Linker 324 aszendiert die Def-Use-Kette von p1 dadurch, dass er diesen Zeiger zurück zu der Zeigerzuordnung im Pseudocodeblock 620 verfolgt, und dann die Variable c1 zurück zu der Deklaration dieser Variable innerhalb des Pseudocodeblocks 610 verfolgt.
-
Für jeden Zeiger, der mit den Speicherzugriffsoperationen, die im Schritt 404 gesammelt wurden, assoziiert sind, fügt der Geräte-Compiler-und-Linker 324 den Zeiger zu einem Vektor hinzu, wenn dieser Zeiger von einem spezifischen Speicherraum abgeleitet worden ist, ähnlich dem Schritt 406 in dem Verfahren 400. In dem Pseudocode 600 ist der Zeiger p1 von der konstanten Variable c1 abgeleitet, welche im konstanten Speicher residiert. Folglich fügt der Geräte-Compiler-und-Linker 324 p1 zu dem Vektor hinzu. Der Zeiger p3 ist von entweder p1 oder p2 abgeleitet, abhängig von dem Verzweigungsbefehl 632. Da p1 und p2 jeweils vom konstanten und gemeinsamen Speicher abgeleitet sind, kann der mit p3 assoziierte Speicherzugriff nicht zu einem spezifischen Speicherraum aufgelöst werden und p3 wird nicht zu dem Vektor hinzufügt. Der Zeiger p5 ist von einem der konstanten Variablen c1 und c2 abgeleitet und wird folglich, unabhängig davon, welche Abzweigung von dem Verzweigungsbefehl 634 zur Laufzeit gefolgt wird, immer noch von dem konstanten Speicher abgeleitet werden. Folglich fügt der Geräte-Compiler-und-Linker 324 p5 zu dem Vektor hinzu.
-
Der Geräte-Compiler-und-Linker 324 durchläuft (engl. „traverses”) den Vektor und modifiziert, für jeden Zeiger in dem Vektor, die assoziierte Speicherzugriffsoperation zum Abzielen auf den spezifischen Speicherraum, von dem der Zeiger abgeleitet wurde, ähnlich dem Schritt 408 des Verfahrens 400. Dabei modifiziert der Geräte-Compiler-und-Linker 324 die Speicherzugriffsoperationen von p1 und p5 derart, dass diese spezifisch auf konstanten Speicher abzielt. Die mit p3 assoziierte Speicherzugriffsoperation wird als eine generische Speicherzugriffsoperation gelassen.
-
Nachdem das Verfahren 400 von 4 auf dem Pseudocode 600 durchgeführt worden ist, mag der Geräte-Compiler-und-Linker 324 dann den Pseudocode 600 dadurch neu verarbeiten (engl. „re-process”), dass er das Verfahren 500 von 5 auf dem Pseudocode 600 durchführt, wie es unten anhand eines Beispiels diskutiert wird.
-
Die folgende Beschreibung stellt lediglich ein Beispiel dar, in dem der Geräte-Compiler-und-Linker 324 das Verfahren 500 durchführt, das oben in Zusammenhang mit der 5 beschrieben wurde. In diesem Beispiel deszendiert (engl. „descends”) der Geräte-Compiler-und-Linker 324 erst die Def-Use-Kette von jeder konstanten Adresse bis ein Speicherzugriff erreicht wird, ähnlich dem Schritt 502 des Verfahrens 500. Der Geräte-Compiler-und-Linker 324 aszendiert die Def-Use-Kette von den konstanten Variablen c1 und c2, die im Pseudocodeblock 610 deklariert wurden, bis zum Erreichen der mit diesen konstanten Variablen assoziierten Speicherzugriffsoperationen. Wie gezeigt kann c1 herunter zu den Speicherzugriffsoperationen, die die Zeiger p1, p3 und p5 einbinden, verfolgt werden, während c2 herunter zu den Speicherzugriffsoperationen, die lediglich den Zeiger p5 einbinden, verfolgt werden kann.
-
Für jede der Speicherzugriffsoperationen, die von einer bestimmten konstanten Deklaration abgeleitet sind, markiert der Geräte-Compiler-und-Linker 324 diese konstante Deklaration als „muss verlagert werden”, wenn der Speicherzugriff nicht auf einen spezifischen Speicherraum aufgelöst wird, ähnlich dem Schritt 504 des Verfahrens 500. Wie es oben in dem vorhergenden Beispiel diskutiert wurde, wurde die Speicherzugriffsoperation, die mit dem Zeiger p3 assoziiert ist, als eine generische Speicherzugriffsoperation gelassen, und so markiert der Geräte-Compiler-und-Linker 324 die konstante Deklaration, die mit dieser Speicherzugriffsoperation assoziiert ist, (die Deklaration für c1) als „muss verlagert werden”.
-
Dann erzeugt der Geräte-Compiler-und-Linker 324 eine Abhängigkeitsliste für jeden Speicherzugriff, ähnlich dem Schritt 506 des Verfahrens 500. Der Geräte-Compiler-und-Linker 324 ist konfiguriert zum Identifizieren jeglicher Abhängigkeitslisten, die konstanten Adressen mit konstanten Deklarationen enthalten, die als „muss verlagert werden” markiert sind, ähnlich dem Schritt 508 des Verfahrens 500. Im Pseudocode 600 ist die mit dem Zeiger p1 assoziierten Speicherzugriffsoperation abhängig von c1, die als „muss verlagert werden” markiert wurde. In ähnlicher Weise ist die Speicherzugriffsoperation, die mit dem Zeiger p3 assoziiert ist, abhängig von c1 und die Speicherzugriffsoperation, die mit dem Zeiger p5 assoziiert ist, ist auch abhängig von c1. Folglich würde der Geräte-Compiler-und-Linker 324 die Abhängigkeitslisten identifizieren, die mit diesen Speicherzugriffsoperationen assoziiert sind.
-
Der Geräte-Compiler-und-Linker 324 würde dann die Speicherzugriffsoperationen, die mit den identifizierten Abhängigkeitslisten assoziiert sind, als „muss verlagert werden” markieren, ähnlich dem Schritt 510 des Verfahrens 500. In dem hierin beschriebenen Beispiel würde der Geräte-Compiler-und-Linker 324 alle die Speicherzugriffsoperationen, die im Pseudocodeblock 640 gezeigt sind, als „muss verlagert werden” markieren.
-
Der Geräte-Compiler-und-Linker 324 würde dann jegliche andere konstanten Deklarationen, die mit konstanten Adressen in den identifizierten Abhängigkeitslisten assoziiert sind, als „muss verlagert werden” markieren, ähnlich dem Schritt 512 des Verfahrens 500. In dem Pseudocode 600 würde der Geräte-Compiler-und-Linker 324 feststellen, dass die Speicherzugriffsoperation für p5 abhängig von der konstanten Variable c2 ist, und da die Abhängigkeitsliste für diese Speicherzugriffsoperation früher identifiziert wurde, würde die konstante Variablendeklaration für c2 dann auch als „muss verlagert werden” markiert werden.
-
Der Geräte-Compiler-und-Linker 324 würde dann jede als „muss verlagert werden” markierte konstante Variablendeklaration derart modifizieren, dass sie im globalen Speicher residieren wird, ähnlich dem Schritt 514 des Verfahrens 500, und würde dann jede als „muss verlagert werden” markierte Speicherzugriffsoperation derart modifizieren, dass sie auf globalen Speicher abzielt, ähnlich dem Schritt 516 des Verfahrens 500. Dabei mag der Geräte-Compiler-und-Linker 324 auch Daten von dem konstanten Speicherraum zu dem globalen Speicherraum befördern, falls erforderlich. Durch Ausführen der in diesem Beispiel beschriebenen Technik verlagert der Geräte-Compiler-und-Linker 324 alle konstanten Speichervariable und Speicherzugriffsoperationen, so dass diese jeweils in globalem Speicher residieren und auf den globalen Speicher abzielen, wodurch Situationen vermieden werden, in denen eine generische Speicherzugriffsoperation auf konstanten Speicher in Abhängigkeit von dem Ergebnis eines Verzweigungsbefehls abzielen oder nicht abzielen mag.
-
Insgesamt ist ein Geräte-Compiler-und-Linker konfiguriert zum Optimieren von Programmcode einer Coprozessor-geeignete Anwendung durch Auflösen generischer Speicherzugriffsoperationen innerhalb dieses Programmcodes, so dass diese auf spezifische Speicherräume abzielen. In Situationen, in denen eine generische Speicherzugriffsoperation nicht aufgelöst werden kann und auf konstanten Speicher abzielen mag, werden konstante Variable, die mit diesen generischen Speicherzugriffsoperationen assoziiert sind, derart verlagert, dass sie im globalen Speicher residieren.
-
Eine Grafikverarbeitungseinheit (GPU) ist vorteilhafterweise nicht dazu gezwungen, alle generischen Speicherzugriffsoperationen zur Laufzeit aufzulösen, wodurch Ressourcen gespart werden und die Ausführung der Anwendung beschleunigt wird. Die GPU ist des Weiteren dazu befähigt, zusätzliche Programmcodeoptimierungen mit dem Programmcode der Anwendung durchzuführen, einschließlich eines Neuordnen des Speicherzugriffs und einer Aliasanalyse, was die Ausführung des Programmcodes weiter beschleunigt.
-
Eine Ausführungsform der Erfindung mag als ein Programmprodukt zur Verwendung mit einem Computersystem implementiert werden. Das Programm bzw. die Programme des Programmprodukts definiert bzw. definieren Funktionen der Ausführungsformen (einschließlich der hierin beschriebenen Verfahren) und kann bzw. können auf einer Vielfalt von computerlesbaren Speichermedien enthalten werden. Beispielhafte computerlesbare Speichermedien umfassen, sind aber nicht darauf begrenzt: (i) nicht-schreibbare Speichermedien (zum Beispiel schreibgeschützte (engl. „read-only”) Speichervorrichtungen innerhalb eines Computers, wie zum Beispiel CD-ROM-Discs, die mittels eines CD-ROM-Laufwerks lesbar sind, Flash-Speicher, ROM-Chips oder jede andere Art von nicht-flüchtigem Festkörper-Halbleiterspeicher (engl. „solid-state non-volatile semiconductor memory”)), auf welchen Informationen permanent gespeichert werden; und (ii) schreibbare Speichermedien (zum Beispiel Floppy-Disks in einem Diskettenlaufwerk oder Festplattenlaufwerk oder jede Art von Festkörper-Halbleiterspeicher mit wahlfreiem Zugriff (engl. „solid-state random-access semiconductor memory”)), auf welchem veränderbare Informationen gespeichert sind.
-
Die Erfindung ist mit Bezug auf spezifische Ausführungsformen oben beschrieben worden. Fachleute werden aber verstehen, dass verschiedene Modifikationen und Änderungen davon gemacht werden können, ohne von dem breiteren Geist und Umfang der Erfindung, wie sie in den angehängten Patentansprüchen dargestellt ist, abzuweichen. Die vorhergehenden Beschreibung und Zeichnungen sind folglich eher in einer illustrativen als in einer restriktiven Bedeutung zu beachten.