-
HINTERGRUND DER ERFINDUNG
-
Gebiet der Erfindung
-
Die vorliegende Erfindung bezieht sich generell auf dynamische Speicherallokation und spezifischer auf eine virtuelle Speicherstruktur für Coprozessoren, die Speicherallokationsbegrenzungen haben.
-
Beschreibung der verwandten Technik
-
Einige konventionelle Coprozessoren haben Speicherallokationsbegrenzungen und sind nicht imstande, Speicher während Ausführung eines Programms dynamisch zu allokieren. Diese konventionellen Coprozessoren begrenzen ein Programm auf eine maximale Menge von Speicher, die zu dem Programm allokiert wird, vor der Ausführung des Programms beginnt. Für einige Programme ist die maximale Menge von Speicher, die während der Ausführung benötigt werden mag, aber nicht bekannt. Wenn, während der Ausführung, die zu dem Programm allokierte Menge von Speicher zu gering ist, dann schlägt die Ausführung des Programms fehl.
-
Folglich ist das, was auf dem technischen Gebiet benötigt wird, eine Technik zum Bereitstellen von zusätzlichem Speicher für ein Programm während Ausführung.
-
ZUSAMMENFASSUNG DER ERFINDUNG
-
Ein System und ein Verfahren zum dynamischen Allokieren von zusätzlichem Speicher während der Ausführung eines Verarbeitungstasks ermöglichen dem Verarbeitungstask zusätzlichen Speicher zu verbrauchen, der vor Beginn der Ausführung des Verarbeitungstasks nicht allokiert wurde.
-
Verschiedene Ausführungsformen von einem erfindungsgemäßen Verfahren zum Allokieren von Speicher zu einem Programm während Ausführung enthält ein Allokieren eines ersten Puffers innerhalb eines ersten Speichers, auf den eine Mehrzahl von Threads beim Ausführen auf einem Coprozessor zugreifen kann. Während der Ausführung von einem Verarbeitungstask auf dem Coprozessor; wird ein Arbeiterthread, der auf einer zentralen Verarbeitungseinheit ausgeführt wird, benachrichtigt, dass der erste Puffer voll ist. Ein erster Abschnitt eines Swap-Puffers innerhalb eines zweiten Speichers, auf den die Mehrzahl von Threads nicht zugreifen kann, wird während Ausführung allokiert und der erste Puffer wird in den ersten Abschnitt des Swap-Puffers hinein geswapt.
-
Speicher wird während Ausführung eines Programms dynamisch allokiert, wenn das Programm von einem Coprozessor ausgeführt wird, der Speicher-Paging oder -Swapping nicht unterstützt. Der Speicher wird von einem auf einen anderen Prozessor ausführenden Arbeiterthread ausgeführt, der Speicher-Paging oder Swapping unterstützt.
-
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 Erfindung, die oben kurz zusammengefasst wurde, 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 dieser 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 Erfindung konfiguriert ist;
-
2 ist ein Blockdiagramm von einem Parallelverarbeitungssubsystem für das Computersystem von 1, gemäß einer Ausführungsform der Erfindung;
-
3 ist ein Blockdiagramm von der Task/Arbeit-Einheit der 2, gemäß einer Ausführungsform der Erfindung;
-
4A ist ein konzeptuelles Diagramm, das einen Speicher darstellt, auf den ein Coprozessor nicht zugreifen kann, und einen Speicher darstellt, auf den ein der Coprozessor zugreifen kann;
-
4B stellt den Kommunikationspuffer von 4A dar, gemäß einer Ausführungsform der Erfindung;
-
4C stellt ein Verfahren zum dynamischen Allokieren von zusätzlichem Speicher während der Ausführung eines Programms durch den Coprozessor dar, gemäß einer Ausführungsform der Erfindung;
-
5A stellt ein Verfahren zur Leerung des Eingangspuffers von 4A dar, gemäß einer Ausführungsformen der Erfindung; und
-
5B stellt ein Verfahren zur Füllung des Ausgangspuffers von 4A dar, gemäß einer Ausführungsform der Erfindung.
-
DETAILLIERTE BESCHREIBUNG
-
In der folgenden Beschreibung werden zahlreiche spezifische Details dargestellt, 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. In anderen Fällen sind wohl bekannte Merkmale nicht beschrieben worden, um eine Verschleierung der vorliegenden Erfindung zu vermeiden.
-
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. 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 I/O-(Input/Output)-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 (PCI) Express, einen beschleunigten Grafikport (engl. „Accelerated Graphics Port”), oder einen HyperTransport-Link) an die Speicherbrücke 105 gekoppelt; in einer Ausführungsform ist das Parallelverarbeitungssubsystem 112 ein Grafiksubsystem, das Pixel an eine Displayvorrichtung 110 liefert, die jegliche konventionelle Kathodenstrahlröhre, Flüssigkristalldisplay, Licht-Emittierende-Diode-Display oder ähnliches sein mag. Eine Systemdisk 114 ist auch mit der I/O-Brücke 107 verbunden und mag dazu konfiguriert sein, Inhalte und Anwendungen und Daten zu speichern, die von der CPU 102 und dem Parallelverarbeitungssubsystem 112 verwendet werden sollen. Die Systemdisk 114 stellt nichtflüchtigen Speicher für Anwendungen und Daten bereit und mag feste oder entfernbare Festplattenlaufwerke, Flashspeichervorrichtungen und CD-ROM (Compact-Disc-Nur-Lese-Speicher), DVD-ROM (Digital-Versatile-Disc-ROM), Blu-ray, HD-DVD (High-Definition-DVD) oder andere magnetische oder optische Speichervorrichtungen oder Festkörper-Speichervorrichtungen enthalten.
-
Ein Switch 116 stellt Verbindungen zwischen der I/O-Brücke 107 und anderen Bauteilen, wie zum Beispiel einem Netzwerkadapter 118 und verschiedenen Erweiterungskarten (engl. „add-in cards”) 120 und 121, bereit. Andere (nicht explizit dargestellte) Bauteile, einschließlich Universal-Serial-Bus (USB) oder anderer Portanschlüsse (engl. „port connections”), Compact-Disc-(CD)-Laufwerke, Digital-Versstile-Disc-(DVD)-Laufwerke, Filmaufzeichnungsvorrichtungen und ähnliches, mögen auch mit der I/O-Brücke 107 verbunden sein. Die verschiedene 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 PCI-Express, AGP (Accelerated Graphics Port), 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ügen (engl. „joining”) der Speicherbrücke 105, der CPU 102 und der I/O-Brücke 107, um ein Systemauf-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 mehr 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 Peripherievorrichtungen 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 ≥ 1. (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 sowohl auf 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 der 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 von einem Applikationsprogramm über den Gerätetreiber 103 für jeden Stoßpuffer festgelegt werden, um das Scheduling der verschiedenen Stoßpuffer zu steuern.
-
Jetzt wird sowohl auf 2 als auch auf 1 Rückbezug genommen und 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 PCI-Express-Anschluss (engl. „PCI-Express link”), in welchem jeder PPU 202 dedizierte Spuren allokiert bzw. 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 bzw. Komponenten 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 zu 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 Verarbeitungsclusterarray (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 erhalten auszuführende Verarbeitungstasks von einer Arbeitsverteilungseinheit innerhalb einer Task/Arbeit-Einheit (engl. „task/work unit”) 207. Die Arbeitsverteilungseinheit empfängt Zeiger auf Rechenverarbeitungstasks, 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 wahlweise bzw. optional einen Parameter enthalten, der steuert, ob die TMD zu dem Kopf oder Ende einer Liste von Verarbeitungstasks (oder Liste von Zeigern auf die Verarbeitungstasks) hinzugefügt werden soll, wobei eine weitere Stufe der Steuerung über 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 dynamischen Direktzugriffspeicher (engl. „dynamic random access memory”) (DRAM) 220. In anderen Ausführungsformen mag die Anzahl der Partitionseinheiten 215 nicht gleich der Anzahl der Speichervorrichtungen sein. Fachleute durchschnittlicher Kenntnisse 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 Framepuffer 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 bzw. routen. 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 hinein 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 einheitlicher Speicherarchitektur (engl. „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.
-
Wie oben erwähnt, kann jede 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 personlicher Rechner, Server, Arbeitsstationen (engl. „workstations”), Spielkonsolen, eingebetteter Systeme und ähnliches.
-
Übersicht der Taskverarbeitung
-
Jeder GPC 208, der in 2 gezeigt ist, mag zum parallelen Ausführen einer großen Anzahl von Threads konfiguriert sein, wobei der Begriff „Thread” auf eine Instanz eines bestimmten Programmes hinweist, das auf einem bestimmten Satz von Inputdaten ausgeführt wird. In einigen Ausführungsformen werden einzelne-Instruktions-, mehrfache-Daten-(SIMD)-Instruktionsausgabetechniken (engl. „single-instruction, multiple-data (SIMD) instruction issue techniques”) verwendet, um parallele Ausführung von einer großen Anzahl von Threads zu unterstützen, ohne mehrfache unabhängige Instruktionseinheiten bereitzustellen. In anderen Ausführungsformen werden einzelne-Instruktions-, mehrfache-Threads-(SIMT)-Techniken (engl. „single-instruction, multiple-thread (SIMT) techniques”) verwendet, um parallele Ausführung von einer großen Anzahl von generell synchronisierten Threads zu unterstützen, unter Verwendung einen gemeinsamen Instruktionseinheit, die zur Ausgabe von Instruktionen an einen Satz von Verarbeitungsmaschinen (engl. „processing engines”) innerhalb jedes der GPCs 208 konfiguriert ist. Anders als bei einer SIMD-Ausführungsbetriebsart (engl. „SIMD execution regime”), bei der alle Verarbeitungsmaschinen typischerweise identische Instruktionen ausführen, erlaubt die SIMT-Ausführung, dass verschiedene Threads divergierende Ausführungspfade durch ein gegebenes Threadprogramm zügiger folgen. Fachleute werden verstehen, dass eine SIMD-Verarbeitungsbetriebsart eine funktionelle Untermenge von einer SIMT-Verarbeitungsbetriebsart ist.
-
In einer Ausführungsform weist jeder GPC 208 eine Anzahl M von Streaming-Multiprozessoren auf, die jeweils zum Verarbeiten einer oder mehrerer Threadgruppen konfiguriert ist. Die Reihe von Instruktionen, die an einen bestimmten GPC 208 übermittelt wird, bildet einen Thread, wie es hierin früher definiert wurde, und die Sammlung von einer bestimmten Anzahl von Threads, die gleichzeitig überall in (engl. „across”) den Parallelverarbeitungsmaschinen innerhalb eines Streaming-Multiprozessors 310 ausgeführt werden, wird hierin als ein „Warp” oder als eine „Threadgruppe” (engl. „thread group”) bezeichnet. Wie hierin benutzt, bezeichnet eine „Threadgruppe” eine Gruppe von Threads, die gleichzeitig das gleiche Programm auf unterschiedlichen Inputdaten ausführen, wobei ein Thread der Gruppe einer unterschiedlichen Verarbeitungsmaschine innerhalb eines Streaming-Multiprozessors zugeordnet ist. Eine Threadgruppe mag weniger Threads als die Anzahl der Verarbeitungsmaschinen innerhalb des Streaming-Multiprozessors enthalten, in welchem Falle einige Verarbeitungsmaschinen während Zyklen, in denen diese Threadgruppe verarbeitet wird, inaktiv bzw. im Leerlauf sein werden. Eine Threadgruppe mag auch mehr Threads als die Anzahl der Verarbeitungsmaschinen innerhalb des Streaming-Multiprozessors enthalten, in welchem Falle die Verarbeitung in aufeinanderfolgenden Zyklen stattfinden wird. Da jeder Streaming-Multiprozessor bis zu G Threadgruppen gleichzeitig unterstützen kann, folgt es, dass bis zu G·M Threadgruppen zu jedem gegebenen Zeitpunkt im GPC 208 ausgeführt werden können.
-
Eine Mehrzahl von verwandten bzw. in Beziehung stehenden Threadgruppen mag des Weiteren zum gleichen Zeitpunkt innerhalb eines Streaming-Multiprozessors aktiv sein (in verschiedenen Phasen der Ausführung). Diese Sammlung von Threadgruppen wird hierin als ein „Array zusammenarbeitender Threads” (engl. „cooperative thread array”) (CTA) oder „Threadarray” bezeichnet. Die Größe eines bestimmten CTA ist gleich m·k, wobei k die Anzahl der gleichzeitig ausführenden Threads in einer Threadgruppe ist, die typischerweise ein ganzzahliges Vielfaches der Anzahl von Parallelverarbeitungsmaschinen innerhalb des Streaming-Multiprozessors ist, und m die Anzahl von gleichzeitig aktiven Threadgruppen innerhalb des Streaming-Multiprozessors ist. Die Größe eines CTA wird generell von dem Programmierer und der Menge der für das CTA zur Verfügung stehenden Hardware-Ressourcen, wie zum Beispiel Speicher oder Register, bestimmt.
-
Jeder Streaming-Multiprozessor enthält einen Stufe-Eins-(L1)-Cache (engl. „level one cache”) oder nutzt Platz in einem entsprechenden L1-Cache außerhalb des Streaming-Multiprozessors, der zum Ausführen von Lade- und Speicheroperationen (engl. „load and store operations”) benutzt wird. Jeder Streaming-Multiprozessor hat auch Zugriff auf Stufe-Zwei-(L2)-Caches, die von allen GPCs 208 gemeinsam genutzt werden und zum Übertragen von Daten zwischen Threads benutzt werden mögen. Schließlich haben die Streaming-Multiprozessoren auch Zugriff auf externen (engl. „off-chip”) „globalen” Speicher, welcher zum Beispiel Parallelverarbeitungsspeicher 204 und/oder Systemspeicher 104 aufweisen kann. Es ist zu verstehen, dass jeder beliebige Speicher, der extern zur PPU 202 ist, als globaler Speicher benutzt werden mag.
-
Jeder GPC 208 mag eine Speichermanagementeinheit (MMU) aufweisen, die zum Abbilden bzw. Mappen virtueller Adressen auf absolute bzw. physische (engl. „physical”) Adressen konfiguriert ist. In anderen Ausführungsformen mag bzw. mögen die MMU(s) sich innerhalb der Speicherschnittstelle 214 befinden. Die MMU enthält einen Satz von Seitentabelleneinträgen (engl. „page table entries”) (PTEs), die zum Abbilden einer virtuellen Adresse auf eine absolute Adresse einer Fliese (engl. „tile) und wahlweise eines Cachezeilenindex verwendet werden. Die MMU mag Adressübersetzungs-assoziative-Pufferspeicher (TLB) (engl. „address translation lookaside buffers”) oder Adressübersetzungs-parallele-Cachespeicher (engl. „address translation lookaside caches”) aufweisen. Die absolute Adresse wird verarbeitet, um Oberflächendaten-Zugriffslokalität (engl. „surface data access locality”) zu distribuieren, um effiziente Anforderungs-Interleaving (engl. „request interleaving”) zwischen Partitionseinheiten 215 zu erlauben. Der Cachezeilenindex mag benutzt werden, um zu bestimmen, ob eine Anforderung für eine Cachezeile einen Treffer (engl. „hit”) oder einen Fehlschuss (engl. „miss”) ist.
-
Es wird verstanden, dass die hierin beschriebene Kernarchitektur illustrativ ist und dass Variationen und Modifikationen möglich sind. Zum Beispiel, während nur ein GPC 208 gezeigt wird, mag eine PPU 202, wie es in 2 gezeigt ist, jede beliebige Anzahl von GPCs 208 enthalten, die vorteilhafterweise einander funktionell ähnlich sind, so dass der Verlauf der Ausführung nicht davon abhängt, welcher GPC 208 einen gegebenen Verarbeitungstask erhält. Des Weiteren operiert jeder GPC 208 vorteilhafterweise unabhängig von anderen GPCs 208 unter Verwendung separater und individueller Verarbeitungseinheiten, L1-Caches und so weiter.
-
Fachleute mit durchschnittlichen Kenntnissen werden verstehen, dass die in den 1, 2 und 3 dargestellten Architektur den Umfang der vorliegenden Erfindung in keiner Weise begrenzt und dass die hierin beschriebenen Techniken in jeder sachgemäß konfigurierten Verarbeitungseinheit implementiert werden mögen, einschließlich, ohne Begrenzung, einer oder mehrerer CPUs, einer oder mehrerer Mehrkern-CPUs, einer oder mehrerer PPUs 202, eines oder mehrerer GPCs 208, einer oder mehrerer Grafik- oder Sonderzweck-(engl. „special purpose”)-Verarbeitungseinheiten oder ähnliches, ohne den Umfang der Vorliegenden Erfindung zu verlassen.
-
In Ausführungsformen der vorliegenden Erfindung ist es wünschenswert, PPU 202 oder einen anderen bzw. andere Prozessor(en) eines Datenverarbeitungssystems zu benutzen, um allgemeine Berechnungen unter Verwendung von Threadarrays durchzuführen. Jedem Thread in dem Threadarray ist einen eindeutigen Thread-Identifikator (engl. „Thread-ID”) zugeordnet, der während dessen Ausführung für den Thread zugänglich ist. Der Thread-ID, der als ein eindimensionaler oder mehrdimensionaler numerischer Wert definiert werden kann, steuert verschiedene Aspekte von dem Verlauf der Ausführung des Threads. Ein Thread-ID mag zum Beispiel verwendet werden, um zu bestimmen, welchen Teil des Eingangsdatensatzes ein Thread bearbeiten soll, und/oder zu bestimmen, welchen Teil eines Ausgangsdatensatzes ein Thread produzieren oder schreiben soll.
-
Eine Folge bzw. Sequenz von pro-Thread-Instruktionen (engl. „per-thread instructions”) mag zumindest eine Instruktion enthalten, die ein kooperatives Verhalten zwischen dem maßgeblichen (engl. „representative”) Thread und einem oder mehreren anderen Threads des Threadarrays definiert. Die Sequenz von pro-Thread-Instruktionen mag zum Beispiel eine Instruktion, die Ausführung von Operationen für den maßgeblichen Thrwead bei einem bestimmten Punkt in der Sequenz bis zu einem solchen Zeitpunkt zu suspendieren, bei dem ein oder mehr von den anderen Threads diesen bestimmten Punkt erreichen, eine Instruktion für den maßgeblichen Thread, Daten in einem gemeinsam genutzten Speicher, auf den ein oder mehr von den anderen Threads Zugriff haben, zu speichern, eine Instruktion für den maßgeblichen Thread, Daten, die in einem gemeinsam genutzten Speicher, auf den ein oder mehr von den anderen Threads Zugriff basierend auf deren Thread-IDs haben, atomar zu lesen und aktualisieren, oder ähnliche Instruktionen enthalten. Das CTA-Programm kann auch eine Instruktion enthalten, eine Adresse in dem gemeinsamen genutzten Speicher zu berechnen, aus der Daten zu lesen sind, wobei die Adresse eine Funktion von dem Thread-ID ist. Durch Definieren zweckmäßiger Funktionen und durch Bereitstellen von Synchronisierungstechniken können Daten von einem Thread eines CTA in einer gegebenen Stelle in dem gemeinsam genutzten Speicher geschrieben und von einem anderen Thread des gleichen CTA aus dieser Stelle gelesen werden auf eine vorhersehbare Art und Weise. Folglich kann jedes gewünschtes Muster von Datenteilung zwischen Threads unterstützt werden und jeder Thread in einem CTA kann Daten mit jedem anderen Thread in dem gleichen CTA teilen. Der Umfang, wenn überhaupt, der Datenteilung zwischen Threads eines CTA wird von dem CTA-Programm bestimmt; es ist somit zu verstehen, dass die Threads eines CTA in einer gegebenen Applikation, der CTAs verwendet, tatsächlich, in Abhängigkeit von dem CTA-Programm, Daten miteinander teilen oder nicht miteinander teilen mögen, und die Begriffe „CTA” und „Threadarray” werden hierin synonym verwendet.
-
Scheduling von mehreren gleichzeitigen Tasks
-
(engl. „Multiple Concurrent Task Scheduling”)
-
Mehrere Verarbeitungstasks mögen gleichzeitig auf den GPCs 208 ausgeführt werden und ein Verarbeitungstask mag während der Ausführung ein oder mehrere „Kind”-Verarbeitungstasks (engl. „„child” processing tasks”) erzeugen. Die Task/Arbeit-Einheit 207 erhält die Tasks und legt (engl. „schedules”) dynamisch die Ausführung der Bearbeitungstasks und der Kind-Verarbeitungstasks mittels der GPCs 208 zeitlich fest.
-
3 ist ein Blockdiagramm von der Task/Arbeit-Einheit 207 der 2, gemäß einer Ausführungsform der vorliegenden Erfindung. Die Task/Arbeit-Einheit 207 weist eine Taskmanagementeinheit 300 und die Arbeitsverteilungseinheit 340 auf. Die Taskmanagementeinheit 300 organisiert die Tasks, deren Ausführung zeitlich festzulegen ist, basierend auf Ausführungsprioritätsstufen. Für jede Prioritätsstufe speichert die Taskmanagementeinheit 300 eine Liste von Zeigern auf die TMDs 322, die den Tasks in der Schedulertabelle 321 entsprechen, wobei die Liste mit einer verbundenen Liste (engl. „linked list”) implementiert werden kann, und im Folgenden wird eine verbundene Liste angenommen. Die TMDs 322 sind Metadaten, die einen Task darstellen, wie zum Beispiel Konfigurationsdaten und Zustandsinformation, die zum Ausführen des Tasks benötigt werden. Die TMDs 322 mögen in dem PP-Speicher 204 oder in dem Systemspeicher 104, auf den das Parallelverarbeitungssubsystem 112 zugreifen kann, gespeichert sein. Die Rate, mit welcher die Taskmanagementeinheit 300 Tasks akzeptiert und die Tasks in der Schedulertabelle 321 speichert, ist von der Rate entkoppelt, mit der die Taskmanagementeinheit 300 Tasks zur Ausführung zeitlich festlegen (engl. „schedules”), was der Taskmanagementeinheit 300 ermöglicht die Ausführung von Tasks basierend auf Prioritätsinformation oder unter Verwendung anderer Techniken zeitlich festzulegen.
-
Die Arbeitsverteilungseinheit 340 weist eine Tasktabelle 345 mit Slots auf, die jeweils von den TMD 322 für einen Task, der ausgeführt wird, belegt sein mögen. Die Taskmanagementeinheit 300 mag die Tasks zur Ausführung zeitlich festlegen, wenn es einen freien Slot in der Tasktabelle 345 gibt. Wenn es keinen freien Slot gibt, mag ein Task mit höherer Priorität, der keinen Slot belegt, einen Task mit niedrigerer Priorität vertreiben (engl. „evict”), der einen Slot belegt. Wenn ein Task vertrieben wird, wird der Task gestoppt, und falls die Ausführung des Tasks nicht abgeschlossen ist, wird der Task einer verbundenen Liste in der Schedulertabelle 321 hinzugefügt. Wenn ein Kind-Verarbeitungstask erzeugt wird, wird der Kind-Verarbeitungstask einer verbundenen Liste in der Schedulertabelle 321 hinzugefügt. Ein Task wird von einem Slot entfernt, wenn der Task vertrieben wird.
-
Eine TMD 322 einkapselt die Metadaten für einen Verarbeitungstask, einschließlich Netzdimensionen (engl. „grid dimensions”). Die Netzdimensionen (n, m), wobei n und m Ganzzahle sind, spezifizieren die Anzahl von CTAs, die ausgeführt werden, um den Task zu verarbeiten. Zum Beispiel spezifizieren die Netzdimensionen 1, 1 ein einziges CTA und die Netzdimensionen 2, 1 oder 1, 2 spezifizieren zwei CTAs. Netze mögen mehr als zwei Dimensionen haben und alle Dimensionsgrößen sind in der TMD spezifiziert. Jedes CTA benötigt einige Ressourcen der Architektur (engl. „architectural resources”) zur Ausführung. Die Ressourcen der Architektur mögen einen Abschnitt von pro-Task-Speicher, pro-CTA-gemeinsamem-Speicher, pro-Thread-lokalem-Speicher, Registern, CTA-Identifikatoren, Anzahl von Threadgruppen, Anzahl von Threads, Verarbeitungsressourcen oder jeder anderen quantifizierbaren Architekturressource, die von einem Task verbraucht werden mag.
-
Die Arbeitsverteilungseinheit 340 verfolgt (engl. „tracks”) die zur Verfügung stehenden Ressourcen, die zur Verarbeitung eines Tasks benötigt werden, und in einigen Fällen ist die maximale Menge von Ressourcen, die verbraucht werden darf, begrenzt. Weil die PPUs 202 nicht konfiguriert sind zum Unterstützen von dynamischer Speicherallokation, Speicher-Paging bzw. Speicher-Kachelverwaltung oder Speicher-Swapping bzw. Speicher-Umlagerung, muss der Speicher, der zum Speichern von pro-Taks-Daten für ein bestimmtes Anwendungsprogramm benötigt wird, allokiert (oder reserviert) werden, vor das Anwendungsprogramm von den PPUs 202 ausgeführt wird. Weil ein gegebener Verarbeitungstask eine Anzahl von Kind-Tasks erzeugen mag und die Anzahl der Kind-Tasks unbekannt ist, ist es nicht möglich, die maximale Menge von Speicher zu bestimmen, die während der Ausführung eines Tasks verbraucht wird. Eine Lösung zu dieser Herausforderung ist, die Menge von Speicher zu begrenzen, die von jedem CTA verbraucht werden kann. Die Arbeitsverteilungseinheit 340 mag konfiguriert sein zum Sicherstellen, dass die begrenzte pro-CTA-Speichermenge verfügbar ist, als eine Voraussetzung für das Starten jedes CTA, anderenfalls mag der Zustand des CTA nicht gespeichert und nachfolgend wiederhergestellt werden können. Eine andere Lösung ist, einen Mechanismus bereitzustellen, mit dem Speicher während der Ausführung von den Tasks dynamisch allokiert werden kann, so dass die Menge von Speicher, die ein CTA verbrauchen kann, nicht begrenzt ist.
-
VIRTUELLE SPEICHERSTRUKTUR
-
Wie vorher erklärt, haben bestimmte Coprozessor-Vorrichtungen, wie die PPUs 202, nicht die Fähigkeit, Speicher zu allokieren während Threads auf den PPUs Code für ein Anwendungsprogramm ausführen. Folglich muss all Speicher, der von den auf den PPUs 202 ausführenden Threads zu verwenden ist, von dem Host-Prozessor, CPU 102 vor Beginn des Ausführens auf einer der PPUs 202 allokiert werden. Die PPUs 202 sind auch nicht dazu fähig, Speicherstücke (engl. „pieces of memory”) auf Abruf seitenweise ein- oder auszulesen (engl. „page in or page out”), was ein Anwendungsprogramm, das auf den PPUs 202 ausgeführt wird, dazu beschränkt, nicht mehr als der mit den PPUs 202 assoziierte Speicher zu verwenden während Threads laufen.
-
Während solche Beschränkungen für viele Anwendungsprogramme, die für konventionelle Grafikprozessoren vorgesehen sind, akzeptabel gewesen sein mögen, ist eine flexiblere Lösung gewünscht. Insbesondere die Fähigkeiten bzgl. verschachtelter Parallelität von den PPUs 202, die die Fähigkeit hinzufügen, neue Kind-Tasks von Threads zu starten, die bereits auf den PPUs 202 laufen. Während die Menge von Speicher für einen einzigen Start von einem neuen Task oder Kind-Task nicht groß sein mag, erlaubt verschachtelte Parallelität, dass Threads eine unbegrenzte Anzahl von neuen Kind-Tasks starten. Folglich kann die die Menge von Speicher, die auch nur für einen einzigen Task benötigt wird, nicht vorhergesagt werden. Eine virtuelle Speicherstruktur mag verwendet werden, um dynamische Speicherallokation durchzuführen, nachdem ein Task gestartet worden ist.
-
Die virtuelle Speicherstruktur mag implementiert werden, um eine Zuerst-Rein-Zuerst-Raus-Warteschlangestruktur oder einen Speicherpool zu modellieren. Die virtuelle Speicherstruktur ist dazu konfiguriert, unbegrenzt zu wachsen, sogar beim Laufen auf einem Coprozessor (zum Beispiel PPU 202), der weder zum dynamischen Allokieren von Speicher noch zum Allokieren von swapbarem (engl. „swappable”) (seitenspeichertechnik-fähigem (engl. „pageable”)) Speicher fähig ist. Die Fähigkeit, die Menge von Speicher in der virtuellen Speicherstruktur zu erhöhen, erlaubt es einer Warteschlange oder einem Speicherpool, die oder der für die PPUs zur Verfügung stehen, zum Speichern einer unbegrenzten Anzahl von Elementen verwendet zu werden, obwohl sie nur kleine Speicherallokationen benötigen vor dem Beginn der Ausführung von einem Task für eine Anwendungsprogramm. Dynamisches Allokieren von Speicher, indem neue Tasks gestartet werden, ist kritisch, wenn die Anzahl der Kind-Task unbekannt ist, die während der Ausführung eines Anwendungsprogramms erzeugt werden. In manchen Fällen mag die maximale Größe von dem Speicher, der während der Ausführung des Anwendungsprogramms benötigt wird, unwissbar oder wesentlich größer als der zu den PPUs 202 allokierte Speicher sein.
-
Eine virtuelle Speicherstruktur, die eine Warteschlange modelliert, mag jede Standard-Warteschlange-Schnittstelle aufweisen, zum Beispiel push_tail() und pop_head(), ist aber, anders als eine in Schaltungen implementierte Warteschlange, nicht auf eine feste maximale Anzahl von Elementen in der Warteschlange begrenzt. Eine virtuelle Speicherstruktur, die ein Pool modelliert, mag in ähnlicher Weise jede Standard-Zugriff-Schnittstelle aufweisen, zum Beispiel put_entry() und get_entry(), und ist auch nicht auf eine feste maximale Anzahl von Elementen in dem Pool begrenzt. Die virtuelle Speicherstruktur benötigt nur eine kleine Menge von Speicher, die zu der (den) PPU(s) 202 vor-allokiert ist, vor Threads mit dem Ausführen auf der (den) PPU(s) 202 beginnen. Wenn der vor-allokierte Speicher ausläuft, migriert eine Laufzeit, die die virtuelle Speicherstruktur-Implementation handhabt, einige der in dem vor-allokierten Speicher gespeicherten Daten zu Speicher, der für die PPU(s) 202 nicht zugreifbar ist, von der CPU 102 dynamisch allokiert wird und für die CPU 102 aber nicht für die PPU(s) 202 zugreifbar ist. In einer Ausführungsform ist (sind) die PPU(s) konfiguriert zum Erzeugen von Daten, die später von der (den) PPU(s) 202 verbraucht werden. Wenn die Daten, die erzeugt wurde, die Kapazität des vor-allokierten Speichers überschreitet, dann werden die Daten zu zusätzlichem Speicher migriert. Der Hostprozessor, CPU 102, die dynamisches Speicherallokieren und Paging unterstützt, stellt der zusätzliche Speicher bereit zusätzlich zu dem, der für das Anwendungsprogram vor-allokiert wurde und für die PPU(s) 202 zugreifbar ist. Wenn ein Thread, der auf einer PPU 202 ausgeführt wird, anfordert, dass ein Element von der virtuellen Warteschlangestruktur weggenommen (abgehoben (engl. „pop”) oder geholt (engl. „get”)) wird, dann wird die Laufzeit gegebenenfalls die Daten von dem Speicher, der für die PPU(s) 202 nicht zugreifbar ist, zu dem vor-allokierten Speicher migrieren und dann die Daten zu dem Thread retournieren.
-
Die zugrundeliegende von der virtuellen Speicherstruktur durchgeführte Laufzeit und Datenmigration ist unsichtbar für die Threads, die auf der (den) PPU(s) 202 ausgeführt werden. Für Threads, die auf der (den) PPU(s) 202 ausgeführt werden, scheint die virtuelle Speicherstruktur einfach eine Warteschlange oder ein Pool zu sein, die oder das nicht von den normalen Speicherbegrenzungen der PPU(s) 202 begrenzt ist. Mit anderen Worten mag die virtuelle Speicherstruktur weiterhin wachsen, so dass sie größer als der zu der (den) PPU(s) 202 vor-allokierte Speicher oder sogar als der mit der PPU 202 assoziierte physische Speicher (PP-Speicher 204) wird.
-
4A ist ein konzeptuelles Diagramm, das eine virtuelle Speicherstruktur 400 darstellt, die Speicher, der für einen Coprozessor nicht zugreifbar ist, und Speicher, der für den Coprozessor zugreifbar ist, aufweist, gemäß einer Ausführungsform der Erfindung. Die virtuelle Speicherstruktur 400 enthält den Speicher 405, der für den Coprozessor nicht zugreifbar ist, und den Speicher 410, der für den Coprozessor zugreifbar ist. Der Hostprozessor, die CPU 102, kann Speicher allokieren, der für sowohl die CPU 102 als auch für den Coprozessor zugreifbar ist, wobei der Coprozessor eine oder mehrere PPUs 202 ist. Speicher, der für sowohl die CPU 102 als auch den Coprozessor zugreifbar ist, wie zum Beispiel der Speicher 410, der für den Coprozessor zugreifbar ist, mag festgehefteter (engl. „pinned”) Systemspeicher sein, das heißt, ein Abschnitt des Systemspeichers 104. Der Systemspeicher 104 mag direkt an die CPU 102 oder durch die Speicherbrücke 105 an die CPU 102 gekoppelt sein. Der Systemspeicher 104 ist durch den Kommunikationspfad 113 indirekt an das Parallelverarbeitungssubsystem gekoppelt.
-
Wie hierin verwendet, besagt der Begriff Zugreifbar, dass ein Abschnitt des Speichers allokiert oder zur Verwendung für ein bestimmtes Programm reserviert worden ist, das auf der CPU 102 oder auf den PPUs 202 ausgeführt wird. Während Verbindungen zwischen dem Systemspeicher 104 und dem PP-Speicher 204 einen Mechanismus zum Übertragen von Signalen (Lese- und Schreibeanforderungen (engl. „read and write requests”)) zwischen der CPU 102 und dem Systemspeicher 104 und/oder dem PP-Speicher 204 bereitstellen mögen, wird der Systemspeicher 104 und der PP-Speicher nur als zugreifbar für die CPU 102 erachtet, wenn Abschnitte des Systemspeichers 104 und/oder des PP-Speichers 204 zu einem bestimmten Programm allokiert worden sind, das auf der CPU 102 ausgeführt wird. Obwohl Verbindungen zwischen dem Systemspeicher 104 und dem PP-Speicher 204 einen Mechanismus zum Übertragen von Signalen zwischen den PPUs 202 und dem Systemspeicher 104 und/oder dem PP-Speicher 204 bereitstellen mögen, wird der Systemspeicher 104 und der PP-Speicher in ähnlicher Weise nur als zugreifbar für die PPUs 202 erachtet, wenn Abschnitte des Systemspeichers 104 und/oder des PP-Speichers 204 zu einem bestimmten Programm allokiert worden sind, das auf den PPUs 202 ausgeführt wird. Typisch werden Abschnitte des PP-Speichers 204 zu Anwendungsprogrammen allokiert, die auf den PPUs 202 ausgeführt werden, und Abschnitte des Systemspeichers 104 werden zu Anwendungsprogrammen allokiert, die auf der CPU ausgeführt werden, um Speicherzugriffslatenz zu minimieren. Es mag aber Abschnitte des Systemspeichers 104 zu Programmen allokiert werden, die auf den PPUs 202 ausgeführt werden, und es mag Abschnitte des PP-Speichers 204 zu Programmen allokiert werden, die auf der CPU 102 ausgeführt werden.
-
Die CPU 102 unterstützt Speicher-Paging oder Swapping und kann Speicher dynamisch allokieren und kann paging-fähiger oder swap-barer-Speicher in entweder dem Systemspeicher 104 oder dem PP-Speicher 204 allokieren. Der Coprozessor (PPUs 202) kann Speicher nicht dynamisch allokieren und/oder unterstützt nicht Speicher-Paging oder -Swapping und kann keinen paging-fähigen oder swap-baren Speicher allokieren. Vor dem Starten eines Anwendungsprogramms allokiert der Vorrichtungstreiber 103 folglich den Speicher 410, der für den Coprozessor und den Hostprozessor zugreifbar ist, zur Verwendung von den PPUs 202 während der Ausführung des Anwendungsprogramms. Die Menge des Speichers 410, der für den Coprozessor und den Hostprozessor zugreifbar ist, wird zum Zeitpunkt der Allokation festgelegt. Folglich wird die Menge von verfügbarem Speicher im Allokation-Ausgangspuffer (engl. „allocation get buffer”) 412, einem Eingangspuffer (engl. „put buffer”) 413 und einem Kommunikationspuffer 415 zum Zeitpunkt der Allokation festgelegt. Der Ausgangspuffer 412, der Eingangspuffer 413 und der Kommunikationspuffer 415 mögen von sowohl dem Coprozessor als auch von der CPU 102 gelesen oder geschrieben werden.
-
Während der Ausführung des Anwendungsprogramms von den PPUs 202 erzeugen Threads Tasks, die als Daten dargelegt sind und in dem Speicher 410 gespeichert werden, der für den Coprozessor und den Hostprozessor zugreifbar ist. Die erzeugten Tasks werden künftig verbraucht oder verarbeitet und der Speicher, der zum Speichern erzeugter Tasks verbraucht wurde, wird in den Eingangspuffer 413 platziert. Der Eingangspuffer 413 mag konfiguriert sein zum Speichern von Zeigern auf Abschnitte von physischem Speicher. Der Ausgangspuffer 412 mag konfiguriert sein zum Speichern von Zeigern auf Abschnitten von physischem Speicher, die Daten speichern, die einen (erzeugten) Verarbeitungstask darlegen, der von einem Thread verarbeitet werden soll. Wenn ein Thread einen Verarbeitungstask anfordert, nimmt der Thread einen Verarbeitungstask, der in einem Abschnitt des Speichers 410 gespeichert ist, der für den Coprozessor und den Hostprozessor zugreifbar ist, weg (hebt ab (engl. „pops”) oder holt (engl. „gets”)) von dem Ausgangspuffer 412.
-
Wenn die virtuelle Speicherstruktur 400 eine Warteschlange modelliert, dann wird die Reihenfolge aufrechterhalten, in der die Threads Speicherallokationen in den Eingangspuffer 413 hinein schieben (engl. „push”), und zu einem späteren Zeitpunkt werden die Speicherallokationen aus dem Ausgangspuffer 412 in der Zuerst-Rein-Zuerst-Raus-Reihenfolge abgehoben (engl. „popped”). Wenn die virtuelle Speicherstruktur 400 ein Pool modelliert, mögen die Speicherallokationen, die von Daten (erzeugten Verarbeitungstasks) verbraucht sind und von einem Thread, der auf der (den) PPU(s) 202 ausgeführt wird, in den Eingangspuffer 413 hineingefügt wurden, von dem gleichen Thread oder einem anderen Thread, der auf der (den) PPU(s) 202 ausgeführt wird, aus dem Ausgangspuffer 412 in einer anderen Reihenfolge herausgeholt werden.
-
Da eine begrenzte Menge von Speicher für den Ausgangspuffer 412 und den Eingangspuffer 413 allokiert worden ist, mag der Ausgangspuffer 412 leer werden und der Eingangspuffer 413 mag voll werden. Ein Arbeiterthread (engl. „worker thread”), der auf der CPU 102 ausgeführt wird, überwacht den Status des Ausgangspuffers 412 und des Eingangspuffers 413 durch den Kommunikationspuffer 415. Dem Arbeiterthread ist es garantiert, zumindest ab und zu scheduliert zu werden, um den Kommunikationspuffer 415 zu Pollen. Der Arbeiterthread ist konfiguriert zum dynamischen Allokieren von Swap-Speicher 401, nach Bedarf, um zusätzlichen Speicher zur Allokation für die Threads bereitzustellen, die auf dem Coprozessor ausgeführt werden. Der Arbeiterthread hält Zustandsinformation aufrecht, die für den Swap-Speicher 401 spezifisch ist, zum Beispiel physische Speicherstellen von dem Swap-Speicher, in einem Swap-Zustand 402. Die Menge von Speicher in dem Swap-Speicher 401 beginnt bei null, wird nach Bedarf erhöht, um den Ausgangspuffer 412 erneut zu füllen, und wird reduziert als Speicherallokationen freigegeben werden (wenn Threads nach Beendung eines Verarbeitungstasks aussteigen). Der Swap-Speicher 401 mag nur von der CPU 102 gelesen oder geschrieben werden.
-
Ein Thread, der auf dem Coprozessor ausgeführt wird, mag Verfahren verwenden, die auf auf pop_head() und push_tail() basieren, um einen Verarbeitungstask aus dem Ausgangspuffer 412 herauszuholen und eine Speicherallokation zum Speichern eines Verarbeitungstasks in dem Eingangspuffer 413 anzufordern. Wenn die virtuelle Speicherstruktur 400 eine Warteschlange modelliert, dann ist der Ausgangpuffer 412 der Kopf (engl. „head”) der Warteschlange, der Swap-Speicher 401 (falls vorhanden) ist die Mitte der Warteschlange und der Eingangspuffer 413 ist das Ende (engl. „tail”) der Warteschlange. Die Größe der Warteschlange kann wachsen während der Arbeiterthread die Größe des Swap-Speichers 401 dynamisch erhöht.
-
4B zeigt den Kommunikationspuffer 415 von 4A, gemäß einer Ausführungsform der Erfindung. Wenn ein Coprozessor-Thread eine Speicherallokation anfordert und anfordert, dass die Speicherallokation (erzeugten Verarbeitungstask oder andere Daten) in den Eingangspuffer 413 hineingefügt wird, und der Eingangspuffer 413 voll ist, dann benachrichtigt der Thread den Arbeiterthread durch Schreiben einer Eingangspuffer-Entleeren-Benachrichtigung (engl. „empty puf puffer notification”) 416 in dem Kommunikationspuffer 415. Der Arbeiterthread, der auf der CPU ausgeführt wird, liest die Eingangspuffer-Entleeren-Benachrichtigung 416 kontinuierlich, periodisch oder nach einer anderen asynchronen Benachrichtigung (zum Beispiel einem von der CPU 102 erhaltenen Interrupt). Wenn der Arbeiterthread feststellt, dass ein Coprozessor-Thread eine Benachrichtigung durch Schreiben (oder Setzen) der Eingangspuffer-Entleeren-Benachrichtigung 416 gesendet hat, dann löscht der Arbeiterthread die Eingangspuffer-Entleeren-Benachrichtigung 416.
-
Wenn der Swap-Speicher 401 nicht genügend Kapazität hat, um den Eingangspuffer 413 zu speichern, dann mag der Arbeiterthread dynamisch zusätzlichen Speicher als Swap-Speicher 401 allokieren. Der in dem Swap-Speicher 401 zusätzlich benötigten Speicher wird vom Speicher allokiert, der für den Coprozessor nicht zugreifbar ist. Der Arbeiterthread aktualisiert den Swap-Zustand 412, um den neulich allokierten zusätzlichen Speicher in dem Swap-Speicher 401 zu verfolgen. Die Allokationen in dem Swap-Speicher 401 mögen unter Verwendung einer verbundenen Liste (engl. „linked list”) verfolgt werden. Der Arbeiterthread kopiert dann die Inhalte des Eingangspuffers 413 zu dem Swap-Speicher 401 und verbraucht dabei einen Teil der Kapazität des Swap-Speichers 401. Nachdem der Arbeiterthread die Inhalte des Eingangspuffers 413 zu dem Swap-Speicher 401 verschieben hat, sind die Inhalte des Eingangspuffers 413, die für den Coprozessor zugreifbar waren, für den Coprozessor nicht mehr zugreifbar, weil der Swap-Speicher 401 in dem Speicher gespeichert ist, der für den Coprozessor nicht zugreifbar ist. Wenn die Inhalte von dem Coprozessor benötigt werden, mögen die Inhalte von dem Swap-Speicher 401 in den Ausgangspuffer 412 hinein verschoben werden, wie es hierin weiter beschrieben wird.
-
Sobald der Arbeiterthread den Eingangspuffer 413 entleert hat, schreibt der Arbeiterthread die Eingangspuffer-Entleeren-Erledigung 418 in dem Kommunikationspuffer 415, um den Coprozessor-Thread zu benachrichtigen, dass die Eingangspuffer 413 entleert worden ist. Der Coprozessor-Thread liest und löscht dann die Eingangspuffer-Entleeren-Erledigung 418. Die Eingangspuffer-Entleeren-Erledigung 418 mag ein einziges Bit im Kommunikationspuffer 415 sein, das von dem Arbeiterthread, der auf der CPU 102 ausgeführt wird, geschrieben und von den Coprozessor-Threads gelesen und gelöscht werden kann.
-
Wenn ein Coprozessor-Thread versucht, Daten aus dem Ausgangspuffer 412 abzurufen, die zuvor in der virtuellen Speicherstruktur 400 gespeichert wurden, zum Beispiel einen Verarbeitungstask, der jetzt zum Beginnen der Ausführung bereit ist, und der Ausgangspuffer 412 leer ist, dann benachrichtigt der Thread den Arbeiterthread durch Schreiben einer Ausgangspuffer-Füllen-Benachrichtigung 420 in dem Kommunikationspuffer 415. Der Arbeiterthread, der auf der CPU ausgeführt wird, liest die Ausgangspuffer-Füllen-Benachrichtigung 420 kontinuierlich, periodisch oder nach einer anderen asynchronen Benachrichtigung (zum Beispiel einem von der CPU 102 erhaltenen Interrupt). Wenn der Arbeiterthread feststellt, dass ein Coprozessor-Thread eine Benachrichtigung durch Schreiben (oder Setzen) der Ausgangspuffer-Füllen-Benachrichtigung 420 gesendet hat, dann löscht der Arbeiterthread die Ausgangspuffer-Füllen-Benachrichtigung 420. Die Ausgangspuffer-Füllen-Benachrichtigung 420 mag ein einziges Bit im Kommunikationspuffer 415 sein, das von Coprozessor-Threads geschrieben und von dem Arbeiterthread, der auf der CPU 102 ausgeführt wird, gelesen und gelöscht werden kann.
-
Wenn der Swap-Speicher 401 leer ist, stellt der Arbeiterthread fest, ob der Eingangspuffer 413 nicht leer ist, und wenn dem so ist, dann verschiebt der Arbeiterthread einen oder mehreren erzeugten Tasks von dem Eingangspuffer 413 zu dem Ausgangspuffer 412. Der Arbeiterthread prüft, dass der Swap-Speicher 401 leer ist, das heißt, dass keine erzeugten Tasks im Swap-Speicher 401 gespeichert sind, vor er den Eingangspuffer 413 prüft, so dass die FIFO-Reihenfolge aufrechterhalten wird für Daten, die in der virtuellen Speicherstruktur 400 gespeichert worden sind, wenn die virtuelle Speicherstruktur 400 eine Warteschlange modelliert. Wenn der Swap-Speicher 401 gemäß dem Swap-Zustand 402 nicht leer ist, dann kopiert der Arbeiterthread erzeugte Tasks, die im Swap-Speicher 401 gespeichert sind, in den Ausgangspuffer 412 hinein. Der Swap-Zustand 402 wird aktualisiert, um anzuzeigen, dass der Abschnitt des Swap-Speichers 401, der den Ausgangspuffer 412 gefüllt hat, für Allokation verfügbar ist. In einer Ausführungsform mag der Abschnitt des Swap-Speichers 401 von dem Speicher, der für den Coprozessor nicht zugreifbar ist, de-allokiert oder von dem Swap-Speicher 401 befreit werden.
-
Sobald der Arbeiterthread den Ausgangspuffer 412 wieder gefüllt hat, schreibt der Arbeiterthread die Ausgangspuffer-Füllen-Erledigung 422 in dem Kommunikationspuffer 415, um den Coprozessor-Thread zu benachrichtigen, dass die Ausgangspuffer 412 gefüllt worden ist. Der Coprozessor-Thread liest und löscht dann die Ausgangspuffer-Füllen-Erledigung 422. Die Ausgangspuffer-Füllen-Erledigung 422 mag ein einziges Bit im Kommunikationspuffer 415 sein, das von dem Arbeiterthread, der auf der CPU 102 ausgeführt wird, geschrieben und von den Coprozessor-Threads gelesen und gelöscht werden kann.
-
Die Threads, die auf dem Coprozessor ausgeführt werden, kommunizieren mit dem Arbeiterthread durch den Kommunikationspuffer 415 unter Verwendung eines Protokolls der Handshake-Art (engl. „handshake-type protocol”). Andere Handshake-Mechanismen mögen verwendet werden, die auch sicherstellen, dass die Kommunikation zwischen der CPU 102 und den PPUs 202 kohärent ist. Weil mehrere Coprozessor-Threads versuchen mögen, gleichzeitig Daten von dem Ausgangspuffer 412 zu erhalten und/oder gleichzeitig Daten (zum Beispiel eine erzeugte Task-Struktur) in den Eingangspuffer 413 einzufügen, sollten die Daten des Weiteren unter Verwendung von atomaren Operationen eingefügt und retourniert werden, um eine konsistente virtuelle Speicherstruktur 400 zu garantieren. Des Weiteren sollte eine Zugriffssperre (engl. „lock”) erworben bzw. eingesetzt (engl. „acquired”) werden, um sicherzustellen, dass nur ein einziger Coprozessor-Thread auf den Kommunikationspuffer 415 zugreift, um den Arbeiterthread zu benachrichtigen, dass er den Ausgangspuffer 412 wieder auffüllen oder den Eingangspuffer 413 entleeren soll. Die Zugriffssperre sollte nicht aufgehoben werden, vor der Arbeiterthread die Erledigung der Wiederauffüll- oder Entleer-Operation bestätigt hat durch Schreiben des Kommunikationspuffers 415, um den Handshake zu vollenden. Während die Zugriffssperre-Technik verwendet wird, um Einziger-Erzeuger-Einziger-Verbraucher-Zugriffe (engl. „single-producer single-consumer accesses”) für die virtuelle Speicherstruktur 400 durchzusetzen, mögen andere komplizierte Mehrere-Erzeuger-Mehrere-Verbraucher-Protokolle implementiert werden.
-
4C stellt ein Verfahren 440 zur dynamischen Allokation von zusätzlichem Speicher während Ausführung eines Programms durch einen Coprozessor dar, gemäß einer Ausführungsform der Erfindung. Obwohl die Verfahrensschritte in Zusammenhang mit den Systemen der 1, 2, 3, 4A und 4B beschrieben werden, werden Fachleute verstehen, dass jedes System, das zum Ausführen der Verfahrensschritte konfiguriert ist, in jeder Reihenfolge, im Bereich der Erfindungen enthalten ist.
-
Bei Schritt 445 allokiert der Vorrichtungstreiber 103 (zum Beispiel ein CUDA-Vorrichtungstreiber) einen ersten Puffer, den Eingangspuffer 413 innerhalb eines ersten Speichers, der für eine Mehrzahl von Threads zugreifbar ist, wenn diese auf einem Coprozessor, wie einen oder mehreren PPus 202, ausgeführt werden. Der erste Speicher ist Speicher 410, der für den Coprozessor und den Hostprozessor zugreifbar ist, wie es in 4A gezeigt ist. Bei Schritt 450 allokiert der Vorrichtungstreiber 103 einen zweiten Puffer, den Ausgangspuffer 412 innerhalb des ersten Speichers. Bei Schritt 455 allokiert und initialisiert der Vorrichtungstreiber 103 einen dritten Puffer, den Kommunikationspuffer 415 innerhalb des ersten Speichers. Der Kommunikationspuffer 415 wird initialisiert, um die mit den ersten und zweiten Puffern assoziierten Benachrichtigungen zu löschen und um die Indikationen, dass der Arbeiterthread die Verarbeitung der Benachrichtigungen vollendet hat, zu löschen.
-
Bei Schritt 460 wird ein Verarbeitungstask von dem Coprozessor ausgeführt. Bei Schritt 465 stellt ein Coprozessor-Thread fest, ob eine Speicheranforderung fehlschlägt, das heißt, ob der Eingangspuffer 413 voll ist oder ob der Ausgangspuffer 412 leer ist. Wenn die Speicheranforderung beim Schritt 465 nicht fehlschlägt, dann fügt der Coprozessor-Thread einen erzeugten Task in den Eingangspuffer 413 hinein oder erhält einen erzeugten Task von dem Ausgangspuffer 412, und die Ausführung des Verarbeitungstasks wird beim Schritt 460 fortgesetzt. Wenn die Speicheranforderung beim Schritt 465 fehlschlägt, dann benachrichtigt der Coprozessor-Thread bei Schritt 470 einen Arbeiterthread, der auf der CPU ausgeführt wird, dass der erste Puffer voll ist oder dass der zweite Puffer leer ist.
-
Bei Schritt 475 allokiert der Arbeiterthread dynamisch einen ersten Abschnitt des Swap-Puffers 401 innerhalb eines zweiten Speichers, der für die Mehrzahl von Threads während der Ausführung nicht zugreifbar ist, um den Eingangspuffer 413 zu speichern, wenn der Eingangspuffer 413 voll ist. Der zweite Speicher ist der Speicher 405, der für den Coprozessor nicht zugreifbar ist. Wenn der Swap-Puffer 401 leer ist, allokiert der Arbeiterthread zuerst Speicher, der für den Coprozessor nicht zugreifbar ist, dynamisch zu dem Swap-Puffer 401. Wenn der Ausgangspuffer 412 leer ist, allokiert der Arbeiterthread einen ersten Abschnitt des Swap-puffers 401, der erzeugte Tasks speichert, zum Swappen in den Ausgangspuffer 412 hinein. Bei Schritt 480 swapt der Arbeiterthread den ersten Abschnitt des Swap-Puffers 401 in den Ausgangspuffer 412 hinein, wenn der Ausgangspuffer 412 leer ist, und swapt den Eingangspuffer 413 in den ersten Abschnitt des Swap-Puffers 401 hinein, wenn der Eingangspuffer 413 voll ist, wodurch der erste Abschnitt des Swap-Puffers 405 für den Coprozessor während der Ausführung des Verarbeitungstasks zugreifbar gemacht wird.
-
5A stellt ein Verfahren zum Leeren des Eingangspuffers 413 dar, gemäß einer Ausführungsform der Erfindung. Obwohl die Verfahrensschritte in Zusammenhang mit den Systemen der 1, 2, 3, 4A und 4B beschrieben werden, werden Fachleute verstehen, dass jedes System, das zum Ausführen der Verfahrensschritte konfiguriert ist, in jeder Reihenfolge, im Bereich der Erfindungen enthalten ist. Bei Schritt 555 fordert ein Coprozessor-Thread eine Allokation zum Speichern von Daten, zum Beispiel einer Task-Struktur, von dem Eingangspuffer 413 an. Bei Schritt 510 stellt der Coprozessor-Thread fest, ob der Eingangspuffer 413 voll ist, und wenn dies nicht der Fall ist, führt der Coprozessor-Thread bei Schritt 565 eine atomare Operation durch, um eine Speicherallokation zu dem Eingangspuffer 413 zu retournieren. Die Verwendung einer atomaren Operation stellt sicher, dass jede Allokation an einen und nur einen Slot in dem Eingangspuffer 413 retourniert wird, wenn mehrere Coprozessor-Threads gleichzeitig versuchen, Daten in den Eingangspuffer 413 einzufügen.
-
Wenn der Coprozessor-Thread beim Schritt 560 feststellt, dass der Eingangspuffer 413 voll ist, dann versucht der Coprozessor-Thread bei Schritt 570 den Zugriff auf den Eingangspuffer 413 zu sperren, so dass auf den Eingangspuffer nicht von anderen Coprozessor-Threads während des Pufferleeren-Vorgangs zugegriffen werden kann. Bei Schritt 575 stellt der Coprozessor-Thread fest, ob die Sperre erlangt wurde, und wenn dies nicht der Fall ist, dann retourniert der Coprozessor-Thread zum Schritt 560. Anderenfalls erlangt der Coprozessor-Thread die Sperre und bei Schritt 580 benachrichtigt der Coprozessor-Thread den Arbeitsthread, der auf der CPU 102 ausgeführt wird, dass der Eingangspuffer 413 voll ist. Bei Schritt 585 stellt der Coprozessor-Thread fest, ob der Eingangspuffer 413 von dem Arbeitsthread entleert worden ist durch Lesen der Eingangspuffer-Entleeren-Erledigung 418. Der Schritt 585 wird wiederholt, bis der Coprozessor-Thread feststellt, dass der Eingangspuffer 413 entleert worden ist. Dann, bei Schritt 590, retourniert der Coprozessor-Thread die Allokation zu dem Eingangspuffer 413. Bei Schritt 590 entsperrt der Coprozessor-Thread den Eingangspuffer 413, so dass es anderen Coprozessor-Threads erlaubt wird, auf den Eingangspuffer 413 zuzugreifen, einschließlich jeglicher Coprozessor-Threads, die die Sperre beim Schritt 570 nicht erlangen konnten.
-
5B stellt ein Verfahren 500 zum Füllen des Ausgangspuffers 412 dar, gemäß einer Ausführungsform der Erfindung. Obwohl die Verfahrensschritte in Zusammenhang mit den Systemen der 1, 2, 3, 4A und 4B beschrieben werden, werden Fachleute verstehen, dass jedes System, das zum Ausführen der Verfahrensschritte konfiguriert ist, in jeder Reihenfolge, im Bereich der Erfindungen enthalten ist. Bei Schritt 505 fordert ein Coprozessor-Thread Daten von dem Ausgangspuffer 412 an. Bei Schritt 510 stellt der Coprozessor-Thread fest, ob der Ausgangspuffer 412 leer ist, und wenn dies nicht der Fall ist, führt der Coprozessor-Thread bei Schritt 515 eine atomare Operation durch, um Daten aus dem Ausgangspuffer 412 herauszuholen. Die Verwendung einer atomaren Operation stellt sicher, dass alle herausgeholten Daten für einen und nur einen Coprozessor-Thread bereitgestellt wird, wenn mehrere Coprozessor-Threads gleichzeitig versuchen, Daten von den Ausgangspuffer 412 zu erhalten.
-
Wenn der Coprozessor-Thread beim Schritt 510 feststellt, dass der Ausgangspuffer 412 leer ist, dann versucht der Coprozessor-Thread bei Schritt 520 den Zugriff auf den Ausgangspuffer 412 zu sperren, so dass während des Puffer-Wiederauffüllvorgangs keine anderen Coprozessor-Threads auf den Ausgangspuffer 412 zugreifen können. Bei Schritt 525 stellt der Coprozessor-Thread fest, ob die Sperre erlangt wurde, und wenn dies nicht der Fall ist, dann retourniert der Coprozessor-Thread zum Schritt 510. Anderenfalls erlangt der Coprozessor-Thread die Sperre und bei Schritt 530 benachrichtigt der Coprozessor-Thread den Arbeit-Thread, der auf der CPU 102 ausgeführt wird, dass der Ausgangspuffer 412 leer ist. Bei Schritt 535 stellt der Coprozessor-Thread durch Lesen der Ausgangspuffer-Füllen-Erledigung 422 fest, ob der Ausgangspuffer 412 von dem Arbeit-Thread gefüllt worden ist. Der Schritt 535 wird wiederholt, bis der Coprozessor-Thread feststellt, dass der Ausgangspuffer gefüllt worden ist. Dann erhält der Coprozessor-Thread 540 bei Schritt 540 Daten von dem Ausgangspuffer 412. Bei Schritt 545 entsperrt der Coprozessor-Thread den Ausgangspuffer 412, wodurch es anderen Coprozessor-Threads erlaubt wird, auf den Ausgangspuffer 412 zuzugreifen, einschließlich jeder Coprozessor-Threads, die beim Schritt 520 die Sperre nicht erlangen konnten.
-
Zusammenfassend allokiert ein Coprozessor eine Menge von Speicher zu einem Programm in Form eines Eingangspuffers, vor die Ausführung des Programms beginnt. Wenn, während der Ausführung des Programms durch den Coprozessor, eine von einem Thread vorgebrachte Anforderung zum Speichern von Daten in dem Eingangspuffer nicht erfüllt werden kann, weil der Eingangspuffer voll ist, dann benachrichtigt der Thread einen Arbeiterthread. Der Arbeiterthread verarbeitet eine von dem Thread erzeugte Benachrichtigung durch dynamisches Allokieren eines Swap-Puffers innerhalb eines Speichers, auf welchen die Coprozessoren nicht zugreifen können. Der Arbeiterthread speichert dann den Eingangspuffer seitenweise in den Swap-Puffer hinein während der Ausführung des Programms, um den Eingangspuffer zu entleeren. Der Arbeiterthread ermöglicht, dass Speicherallokationen dynamisch erhalten werden während der Ausführung eines Programms durch den Coprozessor. Die Menge von Speicher, die während der Ausführung des Programms verfügbar ist, ist nicht von der Menge von Speicher begrenzt, die für den Eingangspuffer allokiert worden ist.
-
Die Fähigkeit, Speicher während der Ausführung eines Verarbeitungstasks dynamisch zu allokieren, ermöglicht es einem Verarbeitungstask eine unbegrenzte Anzahl von Kind-Tasks zu erzeugen, die auch Kind-Tasks erzeugen mögen. Mit anderen Worten ist die Anzahl der Verschachtelungsstufen für verschachtelte parallele Tasks nicht begrenzt. In ähnlicher Weise ist die Anzahl von Kind-Verarbeitungstasks, die erzeugt werden mögen, und die Menge von Speicher, die jeder Task und Kind-Task verbrauchen mögen, nicht begrenzt basierend auf einer festen Allokation von Speicher. Die virtuelle Speicherstruktur ermöglicht virtueller Allokation von Speicher während Ausführung eines Anwendungsprogramms, auch wenn der Coprozessor, der das Anwendungsprogramm ausführt, Speicher-Paging oder -Swapping nicht unterstützt.
-
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.