DE112021000305T5 - Programmiermodell für ressourcenbeschränkte Planung - Google Patents

Programmiermodell für ressourcenbeschränkte Planung Download PDF

Info

Publication number
DE112021000305T5
DE112021000305T5 DE112021000305.4T DE112021000305T DE112021000305T5 DE 112021000305 T5 DE112021000305 T5 DE 112021000305T5 DE 112021000305 T DE112021000305 T DE 112021000305T DE 112021000305 T5 DE112021000305 T5 DE 112021000305T5
Authority
DE
Germany
Prior art keywords
scheduler
resource
semaphore
data
semaphores
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
DE112021000305.4T
Other languages
English (en)
Inventor
Yury Uralsky
Henry Moreton
Matthijs de SMEDT
Lei Yang
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Nvidia Corp
Original Assignee
Nvidia Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Nvidia Corp filed Critical Nvidia Corp
Publication of DE112021000305T5 publication Critical patent/DE112021000305T5/de
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/50Allocation of resources, e.g. of the central processing unit [CPU]
    • G06F9/5005Allocation of resources, e.g. of the central processing unit [CPU] to service a request
    • G06F9/5027Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals
    • G06F9/5038Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals considering the execution order of a plurality of tasks, e.g. taking priority or time dependency constraints into consideration
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/48Program initiating; Program switching, e.g. by interrupt
    • G06F9/4806Task transfer initiation or dispatching
    • G06F9/4843Task transfer initiation or dispatching by program, e.g. task dispatcher, supervisor, operating system
    • G06F9/4881Scheduling strategies for dispatcher, e.g. round robin, multi-level priority queues
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/50Allocation of resources, e.g. of the central processing unit [CPU]
    • G06F9/5005Allocation of resources, e.g. of the central processing unit [CPU] to service a request
    • G06F9/5011Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resources being hardware resources other than CPUs, Servers and Terminals
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/50Allocation of resources, e.g. of the central processing unit [CPU]
    • G06F9/5005Allocation of resources, e.g. of the central processing unit [CPU] to service a request
    • G06F9/5027Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals
    • G06F9/505Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals considering the load
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/50Allocation of resources, e.g. of the central processing unit [CPU]
    • G06F9/5005Allocation of resources, e.g. of the central processing unit [CPU] to service a request
    • G06F9/5027Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals
    • G06F9/5055Allocation of resources, e.g. of the central processing unit [CPU] to service a request the resource being a machine, e.g. CPUs, Servers, Terminals considering software capabilities, i.e. software resources associated or available to the machine
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/50Allocation of resources, e.g. of the central processing unit [CPU]
    • G06F9/5061Partitioning or combining of resources
    • G06F9/5072Grid computing
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/52Program synchronisation; Mutual exclusion, e.g. by means of semaphores
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T1/00General purpose image data processing
    • G06T1/20Processor architectures; Processor configuration, e.g. pipelining
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06TIMAGE DATA PROCESSING OR GENERATION, IN GENERAL
    • G06T1/00General purpose image data processing
    • G06T1/60Memory management

Landscapes

  • Engineering & Computer Science (AREA)
  • Theoretical Computer Science (AREA)
  • Software Systems (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • Mathematical Physics (AREA)
  • Image Processing (AREA)
  • Image Generation (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

Die vorliegende Technologie erweitert das GPU-Computerprogrammiermodell, um vom System bereitgestellte Daten-Marshalling-Eigenschaften des Grafik-Pipelining zum Steigern der Effizienz und zum Reduzieren des Aufwands bereitzustellen. Ein einfaches Planungsmodell basierend auf skalaren Zählern (z. B. Semaphoren) abstrahiert die Verfügbarkeit von Hardware-Ressourcen. Ressourcenfreigaben können programmgesteuert erfolgen, und ein System-Scheduler muss nur die Zustände solcher Zähler/Semaphore verfolgen, um Arbeitsstartentscheidungen zu treffen. Die Semantik der Zähler/Semaphore wird durch eine Anwendung definiert, welche die Zähler/Semaphore verwenden kann, um zum Beispiel die Verfügbarkeit von freiem Speicherplatz in einem Speicherpuffer, die Menge an Cache-Druck, der durch den Datenfluss im Puffer im Netzwerk verursacht wird, oder das Vorhandensein von zu verarbeitenden Arbeitselementen darzustellen.

Description

  • QUERVERWEIS AUF VERWANDTE ANMELDUNGEN
  • Diese Anmeldung beansprucht die Priorität der vorläufigen US-Patentanmeldung Nr. 62/992,872 , eingereicht am 20.03.2020, durch Bezugnahme hierin aufgenommen.
  • GEBIET
  • Die Technologie hierin bezieht sich auf Grafikverarbeitungseinheiten (graphics processing units - GPUs) und insbesondere auf das Planen von Arbeit, die eine Grafikverarbeitungseinheit ausführen soll.
  • ALLGEMEINER STAND DER TECHNIK & KURZDARSTELLUNG
  • 1 veranschaulicht, wie viele oder die meisten konventionellen Grafikverarbeitungseinheiten (GPUs) in der Lage sind, verschiedene Arten von Arbeitslasten zu verarbeiten, wie z. B. Grafikarbeitslasten und Rechenarbeitslasten. Es gibt Unterschiede zwischen der Planung von Grafikarbeitslasten und Rechenarbeitslasten.
  • Grafikarbeitslasten umfassen typischerweise Sätze von logischen Stufen bei der Verarbeitung von Grafikdaten, die sich auf das Schattieren von Pixeln eines Bildes beziehen. In diesem Zusammenhang entwickelt die Schattierung von Pixeln typischerweise Visualisierungsinformationen (Helligkeit, Farbe, Kontrast oder andere visuelle Eigenschaften), die das Erscheinungsbild eines oder mehrerer Pixel eines Bildes beeinflussen.
  • Eine GPU verwendet normalerweise eine Grafik-Pipeline, um Grafikarbeitslasten zu verarbeiten. Die linke Seite von 1 zeigt eine typische Grafik-Pipeline, die eine Reihe von Shader-Stufen 10 umfasst, die unter Verwendung eines Pipeline-On-Chip-Speichers 11 kommunizieren. Die Grafik-Pipeline stellt somit eine Sequenz von logischen Stufen für die Grafikverarbeitung als Pipeline-Sequenz von Shader-Stufen 10a, 10b, ..., 10n bereit, wobei jede Shader-Stufe 10 in der Sequenz eine jeweilige Grafikberechnung durchführt. In der Grafik-Pipeline, die auf der linken Seite von 1 gezeigt ist, bearbeitet jede Shader-Stufe 10 das/die Ergebnis(se) einer oder mehrerer vorheriger Stufen in der Pipeline und liefert verarbeitete Ergebnisse zur weiteren Verarbeitung durch eine oder mehrere folgende Stufe(n) in der Pipeline. Die über Hardware verteilte Grafikverarbeitung, die durch eine hardwarebasierte Grafik-Pipeline definiert wird, hat sich als sehr effizient erwiesen und ist eine Grundlage für die meisten modernen GPU-Designs.
  • Solche Grafikprogrammiermodelle sind somit um die Vorstellung einer Grafik-Pipeline mit fester Funktion herum aufgebaut, die in einer Erzeuger-Verbraucher-Weise feingeplant ist. In diesem Zusammenhang kann jede Stufe 10 der Grafik-Pipeline separat in einer Pipeline-Weise geplant werden. Die Shader-Stufen 10 in der Pipeline werden basierend auf dem Vorhandensein von Daten gestartet, die von früheren Stufen erzeugt wurden, und der Verfügbarkeit von Ausgaberaum in First-In-First-Out-Speichern (FIFOs) mit fester Funktion, die spätere Stufen speisen. Das Daten-Marshalling wird durch einen sehr gut definierten Satz von vom System bereitgestellten hardwarebasierten Triggern bereitgestellt, um sicherzustellen, dass Datenpakete in geordneter Weise von einer Shader-Stufe zur nächsten fließen und dass eine folgende Stufe erst mit der Arbeit an Daten beginnt, wenn ein vorheriger Schritt der Erzeugung dieser Daten abgeschlossen ist. Darüber hinaus wird das Daten-Marshalling typischerweise durch explizite Definitionen der Anzahl von Eingabedatenattributen, die eine spezielle Grafik-Pipeline-Hardwarestufe (z. B. ein Vertex-Shader) verbraucht, und der Anzahl von Ausgabedatenattributen, die diese erzeugt, unterstützt.
  • Bei einer solchen Grafikverarbeitung umfasst der in vielen (wenn auch nicht allen) Ausführungsformen in solchen Grafik-Pipelines zum Weiterleiten von Daten zwischen Stufen verwendete Speicher 11 lokalen On-Chip-Speicher, auf den schnell und effizient zugegriffen werden kann. Ein derartiger Pipeline-Planungsansatz unter Verwendung von lokalem On-Chip-Speicher hat sich als sehr effizient für die Verarbeitung von Grafikarbeitslasten erwiesen, da er die Verwendung externer Speicherbandbreite und der damit verbundenen Speicherlatenz für den geordneten, formatierten Datenfluss zwischen Pipeline-Stufen umgeht.
  • Analog dazu werden in einer Art Pipeline mehrere Wäscheposten zum Waschen und Trocknen eingeplant. Die Waschmaschine wäscht jede neu eingehende Ladung. Wenn die Waschmaschine mit dem Waschen einer Ladung fertig ist, bewegt der Wäscher die Ladung zum Trockner und startet den Trockner, und lädt dann eine frische Ladung Kleidungsstücke in die Waschmaschine und startet die Waschmaschine. Der Trockner trocknet somit die Wäsche, welche die Waschmaschine fertig gewaschen hat, während die Waschmaschine eine neue Ladung wäscht. Wenn der Trockner fertig ist, entleert der Wäscher die getrockneten Kleidungsstücke zum Bügeln und/oder Falten in einen Korb oder Behälter und bügelt/faltet diese Kleidungsstücke, während die Waschmaschine und der Trockner jeweils frühere Ladungen im gesamten Abfolgeprozess verarbeiten. In einer modernen GPU-Grafik-Pipeline ist der „Wäscher“ Teil des Systems, wobei ein Softwareentwickler einfach davon ausgehen kann, dass er das notwendige Daten-Marshalling bereitstellt, um einen geordneten Datenfluss und eine ordnungsgemäß geplante Verarbeitung durch die Pipeline sicherzustellen. Es sollte jedoch beachtet werden, dass moderne Grafik-Pipelines nicht auf eine lineare Topologie beschränkt sind und dass sich bestimmende Eigenschaften der Pipeline-Architektur eher auf die Art und Weise beziehen, wie Daten zwischen aufeinanderfolgenden Verarbeitungsstufen angeordnet werden, als auf eine bestimmte Topologie.
  • In den frühen Tagen des GPU-Designs war eine solche Pipeline-Grafikverarbeitung mit fester Funktion im Allgemeinen die einzige Arbeitslast, die eine GPU unterstützen konnte, und alle anderen Funktionen wurden in auf der CPU laufender Software ausgeführt. Die ersten Schritte in Richtung GPU-Programmierung waren bescheiden: einige Shader programmierbar zu machen und die Hardware zu verbessern, um Fließkomma-Arithmetik zu unterstützen. Dies öffnete die Tür für einige nicht auf Grafik basierende wissenschaftliche Anwendungen, die auf GPU-Grafik-Pipeline-Hardware ausgeführt werden sollten. Siehe z. B. Du et al., „From CUDA to OpenCL: Towards a performance-portable solution for multi-platform GPU Programming“, Parallel Computing. 38 (8): 391-407 (2012). Grafik-APIs wie OpenGL und DirectX wurden dann verbessert, um einige allgemeine Rechenfunktionen als Grafikprimitive zu formulieren. Darüber hinaus wurden dann allgemeinere Rechen-APIs entwickelt. Z. B. Tarditi et al, „Accelerator: using data parallelism to program GPUs for general-purpose uses“, ACM SIGARCH Computer Architecture News. 34 (5) (2006). NVIDIAs CUDA ermöglichte es Programmierern, die zugrunde liegenden grafischen Konzepte zugunsten gängigerer Hochleistungsrechenkonzepte zu ignorieren, und ebnete den Weg für Microsofts DirectCompute und OpenCL von Apple/Khronos Group. Siehe Du et al. Weiter entwickelte GPU-Hardware, die Allzweck-Hochleistungsrechnen auf Grafikprozessoren („GPGPU“) bietet.
  • Die moderne GPU-Rechenverarbeitung umfasst somit das Arbeiten gemäß einer Allzweck-Anwendungsprogrammierschnittstelle (API) wie CUDA, OpenCL und OpenCompute als Beispiele für digitales Allzweckrechnen. Diese Rechenarbeitslasten können andere sein als diejenigen, die durch eine Grafik-Pipeline mit programmierbarer oder fester Funktion definiert sind, z. B. um einen Satz logischer Rechenstufen zum Verarbeiten von Daten zu definieren, die sich nicht direkt auf das Schattieren von Pixeln in einem Bild beziehen. Einige beispielhafte Rechenoperationen können unter anderem physikalische Berechnungen im Zusammenhang mit der Generierung eines Modells für eine Animation, die Analyse großer Datensätze aus dem wissenschaftlichen oder finanziellen Bereich, Deep-Learning-Operationen, künstliche Intelligenz, Tensorberechnungen und Mustererkennung umfassen.
  • Im Gegensatz zum Grafikprogrammiermodell ist das GPU-Rechenprogrammiermodell derzeit um die Begriffe der Datenparallelberechnung und insbesondere einer flachen massensynchronen Datenparallelität (BSP) herum aufgebaut. Siehe z. B. Leslie G. Valiant, A bridging model for parallel computing, Communications of the ACM, Band 33, Ausgabe 8, August 1990. 1 zeigt beispielhafte GPU-Rechenverarbeitungsstufen 12a, 12b, ..., 12m auf der rechten Seite. Jede parallele Rechenverarbeitungsstufe kann durch den Start vieler paralleler Ausführungsthreads definiert werden, damit eine GPU-Massively-Parallel-Processing-Architektur ausgeführt werden kann. Umfangreiche Arbeitssammlungen 12 werden einzeln gestartet und kommunizieren über den Haupt- oder sonsigen globalen Speicher 13 (siehe 2). Die Sammlungen von Arbeiten können in einer Ausführungsform beliebige Allzweckrechenoperationen oder Programme umfassen, die durch Software, Hardware oder beides definiert oder unterstützt werden.
  • In solchen Rechenmodellen gibt es typischerweise eine Ausführungshierarchie für Rechenlasten. Beispielsweise kann ein „Grid“ in einer Ausführungsform eine Sammlung von Thread-Blöcken umfassen, wobei jeder Thread-Block eine Sammlung von „Kettfäden“ (unter Verwendung einer Textilanalogie) umfasst, die wiederum einzeln ausführende Threads umfassen. Die Organisation eines Thread-Blocks kann verwendet werden, um zu garantieren, dass alle Threads im Thread-Block gleichzeitig ausgeführt werden, was bedeutet, dass sie Daten gemeinsam nutzen (eine Planungsgarantie), miteinander kommunizieren und kooperativ arbeiten können. Es kann jedoch nicht garantiert werden, dass alle Thread-Blöcke in einem Grid gleichzeitig ausgeführt werden. Vielmehr kann ein Thread-Block abhängig von verfügbaren Maschinenressourcen mit der Ausführung beginnen und bis zum Abschluss ausgeführt werden, bevor ein anderer Thread-Block starten kann. Dies bedeutet, dass es keine Garantie für eine gleichzeitige Ausführung zwischen den Thread-Blöcken innerhalb des Grids gibt.
  • Im Allgemeinen werden Grids und Thread-Blöcke nicht in herkömmlichen Grafikarbeitslasten ausgeführt (obwohl angemerkt werden sollte, dass einige dieser allgemeinen Unterscheidungen möglicherweise nicht unbedingt auf bestimmte fortgeschrittene Grafikverarbeitungstechniken wie Mesh-Shader zutreffen, wie sie beispielsweise in US20190236827 beschrieben sind, die das Computerprogrammiermodell an die Grafik-Pipeline übertragen, da Threads kooperativ verwendet werden, um kompakte Meshes (Meshlets) direkt auf dem Chip zur Nutzung durch den Rasterizer zu erzeugen). Darüber hinaus hat herkömmliche Grafikverarbeitung typischerweise keinen Mechanismus zum lokalen Teilen von Daten unter bestimmten ausgewählten Threads mit Garantien der Gleichzeitigkeit entlang den Linien des Thread-Blocks oder Gridmodells, das durch Rechenlasten unterstützt wird.
  • Wie 2 zeigt, wird typischerweise ein gemeinsam genutzter (z. B. Haupt- oder globaler) Speicher 13 verwendet, um Daten zwischen Rechenoperationen 12 weiterzuleiten. Einzelne Grids können jeweils aus dem globalen Speicher 13 lesen und darin schreiben. Es gibt jedoch kein vom System bereitgestelltes Daten-Marshalling oder einen Mechanismus zum Kommunizieren von Daten von einem Grid zum nächsten, außer dem Bereitstellen von Hintergrundspeicher, auf den jedes Grid zugreifen kann. Das System definiert oder beschränkt nicht, welche Daten in ein Grid eingegeben werden oder welche Daten von einem Grid ausgegeben werden. Stattdessen definieren die Rechenanwendungen selbst die Dateneingabe/-ausgabe, Synchronisation und alle weiteren Aspekte der Datenverteilung zwischen Grids, z. B. damit die Ergebnisse einer Grid-Verarbeitung (oder zumindest die speziellen Ergebnisse, von denen die nachfolgende Verarbeitung abhängig ist) vervollständigt und im Speicher gespeichert werden, bevor die nachfolgende Grid-Verarbeitung beginnt.
  • Ein solches Daten-Marshalling bezieht sich darauf, wie Datenpakete von einem Rechenprozess 12a zu einem anderen Rechenprozess 12b geleitet werden, und handhabt die verschiedenen Probleme in Bezug auf die Übertragung einer Nutzlast von einem Rechenprozess zu einem anderen. Zum Beispiel kann Daten-Marshalling beinhalten, Daten von einem Erzeuger zu einem Verbraucher zu übermitteln und sicherzustellen, dass der Verbraucher die Daten erkennen kann und eine konsistente Ansicht der Daten hat. Daten-Marshalling kann auch das Garantieren bestimmter Funktionalität und/oder Handhabungsweise, wie z. B. Cache-Kohärenz und -Scheduling beinhalten, um es einem Verbraucher-Rechenprozess zu ermöglichen, kohärent auf zwischengespeicherte Daten, die ein Erzeuger-Rechenprozess erzeugt hat, zuzugreifen und mit ihnen zu arbeiten. Je nach Anwendung kann Daten-Marshalling das Verschieben oder Kopieren der Daten beinhalten oder erfordern oder nicht. Unter modernen GPU-Compute-APIs wird all dies der Anwendung überlassen. Während dies eine große Flexibilität bietet, bestehen auch einige Nachteile.
  • Daten-Marshalling beinhaltet typischerweise die Bereitstellung einer Art Synchronisation von einem Grid zum nächsten. Wenn jedes Grid unabhängig von allen anderen Grids ist und unabhängig verarbeitet werden kann, ist wenig oder gar keine Synchronisation erforderlich. Dies ist ein bisschen so, als würden Autos auf einer stark befahrenen Mautstraße durch eine Anordnung von Mautstellen fahren, wobei jedes Auto unabhängig eine entsprechende Mautstelle passieren kann und nicht auf ein anderes Auto warten muss. Aber einige Rechenlasten (z. B. bestimmte Graphenalgorithmen, dünn besetzte lineare Algebra und Algorithmen der Bioinformatik u. a.) weisen „unregelmäßige Parallelität“ auf, was bedeutet, dass die Verarbeitung einiger Verbraucher-Grids von der Verarbeitung eines oder mehrerer Erzeuger-Grids abhängen kann.
  • Bei Rechen-APIs ist die Anwendung selbst für die Synchronisation untereinander verantwortlich, um den Datenfluss zwischen ihnen zu organisieren. Wenn beispielsweise ein Verbraucher-Grid die von einem Erzeuger-Grid erzeugten Daten sehen und verwenden möchte, ist die Anwendung dafür verantwortlich, eine Barriere, einen Zaun oder ein anderes Synchronisationsereignis einzufügen, um dem Verbraucher-Grid eine konsistente Ansicht der vom Erzeuger-Grid erzeugten Daten zu bieten. Siehe z. B. US-Patentanmeldung Nr. 16/712,236 , eingereicht am 12.12.2019 mit dem Titel „High Performance Synchronization Mechanisms For Coordinating Operations On A Computer System“, USP 9223578 , USP 9164690 und US20140282566 , die beispielhafte Wege beschreiben, mit denen sich die Grids 12 miteinander synchronisieren und Daten über den globalen Speicher 13 unter Verwendung von Schwerlast-Synchronisierungsprimitiven wie Barrieren oder Zäunen kommunizieren können. Eine solche Zaun-/Barriere-Synchronisationstechnologie kann zum Beispiel eine Synchronisation bereitstellen, die erfordert, dass ein erstes Rechen-Grid das Schreiben von Daten in den Speicher beendet, bevor eine nächste Rechenoperation auf diese Daten zugreift. Gemäß dem massensynchronen Programmiermodell, bei dem die Synchronisation massenweise pro Grid erfolgt, bedeutet dies normalerweise, dass alle Threads des Erzeuger-Grids die Ausführung beenden und ihre Datenergebnisse in den globalen Speicher schreiben müssen, bevor das Verbraucher-Grid mit der Verarbeitung beginnen kann. Die daraus resultierende suboptimale Nutzung der GPU-Verarbeitungsressourcen kann je nach Rechenlast zu erheblicher Zeitverschwendung, verringerter Leistung, verringerter Bandbreite und Energieverschwendung führen.
  • Aufgrund dieser verschiedenen Probleme kann das Ausführungsverhalten, welches das vorliegende Rechenprogrammiermodell zeigt, für einige Arten von Rechenarbeitslasten ineffizient sein. In der Vergangenheit gab es mehrere Versuche zur Verbesserung, damit Anwendungen solche „unregelmäßigen“ parallelen Arbeitslasten ausdrücken können. Beispielsweise hat NVIDIA den CUDA Nested Parallelism mit der Kepler-Architektur eingeführt, der auf unregelmäßige Parallelität in HPC-Anwendungen abzielt. Siehe z. B. USP 8,180,998 ; und Zhang et al., „Taming Irregular Applications via Advanced Dynamic Parallelism on GPUs“ CF '18 (8.-10. Mai 2018, Ischia, Italien). Ein weiteres Beispielprojekt befasste sich mit einem warteschlangenbasierten Programmiermodell für Grafiken. Intels Larrabee-GPU-Architektur (die nicht als Produkt eingeführt wurde) führte Ct ein, das den Begriff der „geflochtenen“ Parallelität aufwies. Siehe z. B. Morris et al, „Kite: Braided Parallelism for Heterogeneous Systems“ (Computer Science 2012). Alle diese Versuche waren relativ begrenzt erfolgreich und versuchten nicht unbedingt, Aspekte des vom Grafik-Pipelinesystem bereitgestellten Scheduling und Daten-Marshalling für die Verwendung mit Rechenlasten zu erfassen.
  • Zur weiteren Erläuterung sei angenommen, dass ein Grid ein Verbraucher und ein anderes Grid ein Erzeuger ist. Das Erzeuger-Grid schreibt Daten in den globalen Speicher, und das Verbraucher-Grid liest diese Daten aus dem globalen Speicher. Im aktuellen synchronen Massenberechnungsmodell müssen diese beiden Grids seriell ausgeführt werden - wobei das Verbraucher-Grid vollständig abgeschlossen ist, bevor das Verbraucher-Grid gestartet wird. Wenn das Erzeuger-Grid groß ist (viele Threads), können einige Threads Nachzügler sein und lange brauchen, bis sie abgeschlossen sind. Dies führt zu einer ineffizienten Nutzung von Rechenressourcen, da das Verbraucher-Grid warten muss, bis die Nachzügler-Threads abgeschlossen sind, bevor es gestartet werden kann. Die Maschinenauslastung sinkt, wenn Threads des Erzeuger-Grids allmählich austreten, was zu einer Ineffizienz im Vergleich zu einer Situation führt, in der alle Threads in beiden Grids gleichzeitig laufen könnten. Aspekte der Technologie hierin vermeiden solche Ineffizienzen und ermöglichen eine kontinuierliche Auslastung, wie beispielsweise in typischen Grafik-Pipelines, die einen kontinuierlichen gleichzeitigen Erzeuger/Verbraucher nutzen, um die Auslastungsvorteile zu erfassen.
  • 3 zeigt zusätzliche Erweiterungs- und Kontraktionsunterstützung (Arbeitsverstärkung und -aggregation) der häufig verwendeten GPU-Pipeline-Grafikverarbeitung. Viele GPUs replizieren bestimmte Shader-Stufen (z. B. Tessellation), um eine vom System aufgerufene parallele Verarbeitung der Eingangsdaten der gleichen Stufe nach Bedarf zu ermöglichen, um Engpässe zu vermeiden und die Datenparallelität zu erhöhen - was sich für bestimmte Arten von Grafikarbeitslasten als nützlich erweist. Eine solche vom System aufgerufene Funktionalität war in der Vergangenheit für vom GPU-System-Scheduler unterstützte Rechenarbeitslasten nicht verfügbar.
  • Daher besteht ein Bedarf an einem neuen Modell, das es ermöglicht, Rechenlasten so zu planen, dass die Planungseffizienz der Grafik-Pipeline erfasst wird.
  • Figurenliste
  • Die folgende detaillierte Beschreibung von beispielhaften, nicht einschränkenden, veranschaulichenden Ausführungsformen ist in Verbindung mit deren Zeichnungen zu lesen:
    • 1 zeigt schematisch eine gespaltene Persönlichkeit einer Grafikverarbeitungseinheit, die eine Rechenverarbeitung und eine Grafikverarbeitung durchführt.
    • 2 zeigt, wie Shader-Stufen unter Verwendung von Pipeline-On-Chip-Speicher miteinander kommunizieren können und wie Rechenprozesse unter Verwendung von globalen Speicher- und Synchronisationsmechanismen miteinander kommunizieren können.
    • 3 zeigt eine beispielhafte, nicht einschränkende Expansions- und Kontraktionsunterstützung für Grafikverarbeitung mit Einschränkungen einer solchen Unterstützung für Rechenprozesse.
    • 4 zeigt ein beispielhaftes nicht einschränkendes Planungsmodell.
    • 5 zeigt ein beispielhaftes nicht einschränkendes Planungsmodell unter Verwendung von Ressourcen mit Startgarantie.
    • 6 zeigt eine beispielhafte ressourcenbeschränkte Planung zwischen einem Erzeuger und einem Verbraucher.
    • 7 zeigt das Beispiel aus 6 für eine ressourcenbeschränkte Planung unter Verwendung von Startschwellenwerten.
    • 8 zeigt das Beispiel von 6 für eine ressourcenbeschränkte Planung, einschließlich Rückmeldungen zur Produktion und zum Verbrauch.
    • 9 zeigt einen beispielhaften nicht einschränkenden Scheduler, der so arbeitet, dass er startet, wenn die Eingabe bereit und die Ausgabe verfügbar ist.
    • 9A zeigt eine detailliertere Ansicht der Graphenausführungsinitiierung.
    • 10 zeigt eine ressourcenbeschränkte Planung mit Warteschlangen,
    • 11 zeigt eine beispielhafte ressourcenbeschränkte Planung unter Verwendung von Daten-Marshalling mit Warteschlangen.
    • 12 zeigt eine beispielhafte ressourcenbeschränkte Zeitplanung mit inneren und äußeren Puts und Gets.
    • 13 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe.
    • 14 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, die eine vorzeitige Freigabe bereitstellt, wenn der Erzeuger keine Ausgabe erzeugt.
    • 15 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, wenn ein späterer Verbraucher Sichtbarkeit benötigt.
    • 16 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, einschließlich einer feinkörnigeren Verfolgung der Ressourcennutzung.
    • 17 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, wenn eine Teilausgabe erzeugt wird.
    • 18 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, wenn ein Erzeuger ungenutzten Speicherplatz in einer Warteschlange freigibt.
    • 19 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, bei der ein Verbraucher verbleibenden Speicherplatz freigibt.
    • 20 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, um neuen Erzeugern einen früheren Beginn zu ermöglichen.
    • 21 zeigt eine beispielhafte, nicht einschränkende Ressourcenfreigabe, die eine Ausgabe mit variabler Größe in der zugehörigen Teilfreigabe ermöglicht.
    • 22 zeigt beispielhafte Zuweisungsschemata für Warteschlangenspeicher, um eine Fragmentierung zu vermeiden.
    • 23 zeigt eine beispielhafte, nicht einschränkende Arbeitsverstärkung, bei der mehrere Verbraucher pro Eintrag gestartet werden.
    • 24 zeigt ein beispielhaftes, nicht einschränkendes Multi-Cask-Startschema (1 zu viele), um mehrere unterschiedliche Verbraucher pro Eintrag zu starten.
    • 25 zeigt eine beispielhafte, nicht einschränkende Arbeitsaggregation, bei der eine Gruppe von Arbeitsaufgaben zu einem einzelnen Verbraucherstart aggregiert wird.
    • 26 zeigt eine beispielhafte, nicht einschränkende Arbeitsaggregation einschließlich Timeout-Ergebnissen bei einem teilweisen Start.
    • 27 zeigt eine beispielhafte Join-Zuordnung mit einer Gruppe von separat berechneten Feldern, die in einer Arbeitsaufgabe gesammelt wurden.
    • 28 zeigt ein beispielhaftes, nicht einschränkendes Sortieren von Arbeit in mehrere Warteschlangen unter Verwendung von Aggregation, um die Ausführung neu zu konvergieren.
    • 29 zeigt ein beispielhaftes, nicht einschränkendes Sortieren von Arbeit in mehrere Warteschlangen für die Shader-Spezialisierung.
    • 30 zeigt ein beispielhaftes, nicht einschränkendes Sortieren von Arbeit in mehrere Warteschlangen für eine kohärente Materialschattierung beim Raytracing.
    • 31 zeigt eine beispielhafte, nicht einschränkende Abhängigkeitsplanung.
    • 32 zeigt beispielhafte, nicht einschränkende Berechnungen, die zu Grafiken geleitet werden.
    • 33 zeigt beispielhafte, nicht einschränkende Berechnungen, die Grafiken speisen, um vollständig flexible Berechnungs-Frontends zu ermöglichen.
  • DETAILLIERTE BESCHREIBUNG BEISPIELHAFTER, NICHT EINSCHRÄNKENDER AUSFÜHRUNGSFORMEN
  • Die vorliegende Technologie erweitert das Computerprogrammiermodell, um einige der vom System bereitgestellten Daten-Marshalling-Eigenschaften des Grafik-Pipelining zum Steigern der Effizienz und zum Reduzieren des Aufwands bereitzustellen. Insbesondere ermöglicht die Technologie hierin Programmierern/Entwicklern, Pipelines von Rechenkernen auf eine Weise zu erstellen, die mit derzeit verfügbaren GPU-Rechen-APIs nicht möglich ist.
  • Beispielhafte nicht einschränkende Ausführungsformen stellen ein einfaches Planungsmodell bereit, das auf skalaren Zählern (z. B. Semaphoren) basiert, welche die Verfügbarkeit von Hardware-Ressourcen abstrahieren. In einer Ausführungsform reserviert/beschafft ein System-Scheduler, der für das Starten neuer Arbeit verantwortlich ist, Ressourcen (entweder „freien“ Speicherplatz oder „bereite“ Arbeitselemente) durch Dekrementieren eines entsprechenden Semaphors, und der Code des Benutzers (d. h. die Anwendung) gibt durch Inkrementieren der Semaphore Ressourcen frei (Verbraucher: durch Hinzufügen zum „freien“ Pool der Ressource, von der sie lesen, Erzeuger: durch Hinzufügen zum „bereiten“ Pool der Ressource, in die sie schreiben). In einer solchen beispielhaften nicht einschränkenden Anordnung kann die Reservierung/Beschaffung stets konservativ durch den Scheduler erfolgen, der die Semaphore dekrementiert, wobei die Ressourcenfreigabe stets durch den Benutzer-(Anwendungs-)Code erfolgt, da dieser bestimmt, wann es angebracht ist, die Freigabe durchzuführen, und zwar immer durch Inkrementieren der Semaphore. In solchen Ausführungsformen können Ressourcenfreigaben somit programmgesteuert erfolgen, und ein System-Scheduler muss nur die Zustände solcher Zähler/Semaphoren verfolgen, um Arbeitsstartentscheidungen zu treffen (Ausweichvorkehrungen können bereitgestellt werden, damit der Scheduler die Semaphoren inkrementieren und dadurch Ressourcen freigeben kann, wenn der Benutzer oder die Anwendungssoftware dies nicht wie vorgesehen tut). Die Freigabe von Ressourcen muss nicht durch die Anwendung des Benutzers erfolgen, sie kann zum Beispiel durch manche Systemsoftware implementiert werden, die sicherstellen kann, dass alle ordnungsgemäßen Abrechnungen durchgeführt werden. Die Semantik der Zähler/Semaphore wird in einer Ausführungsform durch eine Anwendung definiert, welche die Zähler/Semaphore verwenden kann, um zum Beispiel die Verfügbarkeit von freiem Speicherplatz in einem Speicherpuffer, die Menge an Cache-Druck, der durch den Datenfluss im Puffer im Netzwerk verursacht wird, oder das Vorhandensein von zu verarbeitenden Arbeitselementen darzustellen. In diesem Sinne ist unser Ansatz ein „ressourcenbeschränktes“ Planungsmodell.
  • Ein neuer Aspekt dieses Ansatzes besteht darin, dass einer Anwendung die Flexibilität gegeben wird, benutzerdefiniertes Daten-Marshalling zwischen Knoten im Netzwerk zu organisieren, indem effiziente lockfreie Algorithmen unter Verwendung von Warteschlangen oder anderen Datenstrukturen nach Wahl der Anwendung verwendet werden. Indem wir die Verwaltung von Hardwarezählern/Semaphoren, welche die Planungsentscheidungen antreiben, von der Verwaltung solcher Datenstrukturen entkoppeln, ermöglichen wir einen Rahmen zum Ausdrücken von Arbeitsverstärkung und -aggregation - die hilfreiche Aspekte der Grafik-Pipeline-Planung und für eine effiziente Verarbeitung von Arbeitslasten (wie Rechenlasten) mit unterschiedlichen Mengen an Datenparallelität nützlich sind. Es wird ein Ressourcenreservierungssystem bereitgestellt, das Ressourcen zum Zeitpunkt des Starts zuweist, um sicherzustellen, dass die Thread-Blöcke bis zum Abschluss ausgeführt werden können, wodurch Blockaden und die Notwendigkeit eines teuren Kontextwechsels vermieden werden. Das Ressourcenreservierungssystem ist relativ einfach und muss nicht mit der Anzahl der Arbeitselemente oder der Anzahl der gleichzeitig ausgeführten Thread-Gruppen von der gleichen Aufgabe/einem gleichen Knoten skalieren oder wachsen. Beispielsweise betrachtet der Scheduler in einer Ausführungsform während einer solchen Planung für eine bestimmte Aufgabe nur zwei Zähler SF und SR pro Ressource (es wird oder kann mehrere solcher Zählerpaare geben, wenn es mehrere Ressourcen/Stufen in der Pipeline gibt) - was einige Auswirkungen auf die Arten von konstruierbaren Ausführungsknotendiagrammen hat. In einer beispielhaften Ausführungsform werden die Semaphore selbst nicht als Teil des Schedulers betrachtet, sondern werden vielmehr von der Hardwareplattform bereitgestellt, um den Scheduler zu unterstützen. Somit können der Scheduler und die Anwendungen jeweils die Semaphore auf bestimmte Weise manipulieren, und der Scheduler kann die Manipulation der Semaphore durch die Anwendungen überwachen.
  • Ein weiterer Aspekt bezieht sich auf die Anpassung der Erweiterungs-/Kontraktionsunterstützung der Grafik-Pipeline, um solche Konzepte für Rechenlasten nutzbar zu machen - indem dynamische Parallelität bereitgestellt wird.
  • Frühere Versuche zur Planung von Rechenlasten mit unregelmäßiger Parallelität versuchten im Allgemeinen nicht, den Begriff des Gegendrucks direkt in einen Erzeuger-Verbraucher-Datenfluss zu integrieren, was für eine effiziente Planung hilfreich ist und es ermöglicht, dass der Datenfluss auf dem Chip bleibt. Backpressure- Fähigkeit eines Verbrauchers, einen Erzeuger zu verlangsamen, um zu verhindern, dass der Verbraucher von dem vom Erzeuger erzeugten Datenstrom überwältigt wird - ermöglicht das effiziente Streamen großer Datenmengen durch Puffer fester Größe. In der Lage zu sein, Puffer mit fester Größe zuzuweisen, die kleiner als die potenzielle Anzahl von durch sie gestreamten Arbeitselementen sind, ist höchst wünschenswert, da physischer Speicher eine begrenzte Ressource ist und mit vielen anderen Teilen der Anwendung geteilt wird. Grafik-Pipelines unterstützen häufig eine solches Backpressure-Scheduling, siehe z. B. Jonathan Ragan-Kelley, Keeping Many Cores Busy: Scheduling the Graphics Pipeline, Beyond Programmable Shading II (SIGGRAPH Donnerstag, 29. Juli 2010); Kubisch, GPU-gesteuertes Rendering (NVIDIA, GTC Silicon Valley, 4. April 2016); Node US, „Backpressuring in Streams“, https://nodejs.org/en/docs/guides/backpressuring-in-streams/. Eine Alternative wäre die Zuweisung eines ausreichend großen Puffers zwischen Erzeuger und Verbraucher, um den „Worst Case“ auszugleichen, aber die Parallelität der Maschine lässt zu, dass nur ein Bruchteil einer solchen „Worst Case“-Zuordnung gleichzeitig aktiv ist - der Rest der Worst Case-Speicherzuweisung wird verschwendet oder ist im Leerlauf. Backpressure-Scheduling ermöglicht die effiziente Nutzung von Speicherzuweisungen mit fester Größe, wodurch Verschwendung minimiert wird.
  • Der beispielhafte nicht einschränkende Ansatz kann auch ausdrücklich die Notwendigkeit einer Kontextumschaltung jeglicher Arbeit im laufenden Betrieb vermeiden. Beispielsweise kann in einer modernen GPU die Zustandsmenge, die für den Kontextwechsel gespeichert und wiederhergestellt werden muss, zu groß sein, um in Hochleistungsumgebungen praktikabel zu sein. Indem der Scheduler direkt auf die einem Chip auferlegten Ressourcenbeschränkungen aufmerksam gemacht wird, wie z. B. die Menge an verfügbarer On-Chip-Pufferung, ermöglicht unser Ansatz dem Gesamtsystem, die Arbeitslast zu streamen, während die Menge an externer, für die Übertragung transienter Daten erforderlicher Speicherbandbreite minimiert wird.
  • Da wir den Anwendungsbereich von Anwendungen, die von einem Prozessor wie einer GPU verarbeitet werden, auf neuartige Bereiche wie maschinelles Lernen und Raytracing erweitern, wird der vorliegende Ansatz dazu beitragen, das Kernprogrammiermodell voranzutreiben, das zur effizienten Bewältigung solcher Arbeitslasten verwendet wird, darunter solcher, die unregelmäßige Parallelität aufweisen. Insbesondere ermöglichen Beispielfunktionen unseres Modells die Reduzierung und/oder vollständige Eliminierung des externen Speicherverkehrs bei der Planung komplexer Rechenlasten und bieten einen Weg zur Skalierung der Leistung über die Bandbreitengrenze des externen Speichers hinaus.
  • Ein weiterer Aspekt umfasst eine API (Application Programming Interface), die diese Technologie unterstützt. Eine solche API kann auf einer Reihe unterschiedlicher Hardwareplattformen vorhanden sein, und Entwickler können eine solche API zum Entwickeln von Anwendungen verwenden.
  • Noch ein weiterer Aspekt umfasst die vorteilhafte Verwendung von Speicher-Caching, um den Datenfluss zwischen Rechenstufen in einem schnelleren Speicher zu erfassen, wodurch ein On-Chip-Speicher zum Kommunizieren von Daten zwischen Stufen einer Grafik-Pipeline verwendet wird. Dies ermöglicht die Optimierung von Implementierungen durch Nutzung von On-Chip-Speicher, wodurch teure globale (z. B. Frame-Puffer) Off-Chip-Speicheroperationen vermieden werden, indem der Rechendatenfluss in Pipelines geleitet wird, wodurch Bandbreite und Rechenleistung erhöht werden.
  • Noch ein weiterer Aspekt betrifft das Daten-Marshalling, bei dem die Arbeit feinkörniger geplant wird. Anstatt alle Threads im Grid oder einer anderen Sammlung von Threads gleichzeitig zu starten und darauf zu warten, dass alle abgeschlossen sind, können wir ausgewählte Threads oder Gruppen von Threads in einer Pipeline-Weise starten - wodurch eine Feinsynchronisation ermöglicht wird, indem nicht in großen Mengen synchronisiert wird. Das bedeutet, dass wir Erzeuger und Verbraucher gleichzeitig betreiben können - genau wie in einem Pipeline-Modell.
  • Beispielhaftes, nicht einschränkendes Planungsmodell
  • 4 zeigt schematisch ein beispielhaftes, nicht einschränkendes Planungsmodell 100, das eine Scheduling-Grundeinheit zeigt. In dem gezeigten Planungsmodell 100 wird eine Eingangsnutzlast 102 einem Thread-Block 104 bereitgestellt, der eine Ausgangsnutzlast 106 erzeugt. Eines der Merkmale des Planungsmodells 100 ist ein systemdefiniertes Programmiermodell, das explizite Definitionen für eine oder mehrere Eingangsnutzlasten für den Thread-Block 104 und eine oder mehrere Ausgangsnutzlasten aus dem Thread-Block bereitstellt. In einer Ausführungsform definiert die explizite Definition der Nutzlasten 102, 106 die Größen der Datenpakete.
  • Beispielsweise kann die Definition einem allgemeinen Programmmodell entsprechen, das eine explizite Systemdeklaration enthält, dass der Thread-Block 104 N Bytes der Eingangsnutzlast 102 verbrauchen und M Bytes der Ausgangsnutzlast 106 erzeugen wird. Der Thread-Block 104 (und nicht das System in einer Ausführungsform) kümmert sich um die Bedeutung, Interpretation und/oder Struktur der Eingangs- und Ausgangsdatennutzlast 102, 104 und darum, wie viele Daten der Thread-Block tatsächlich von seiner Eingangsnutzlast 102 liest und für jeden Aufruf des Thread-Blocks in seine Ausgangsnutzlast 106 schreibt. Andererseits weiß das System in einer Ausführungsform gemäß dem Planungsmodell, dass die Eingangsnutzlast 102 zur Eingabe durch den Thread-Block 104, und die Größe dieser (für das System undurchsichtigen) Eingangsdatennutzlast bestimmt ist, und gleichermaßen dass die Ausgangsnutzlast 106 für die Ausgabe durch diesen Thread-Block und die Größe dieser (für das System undurchsichtigen) Ausgabedatennutzlast bestimmt ist. Solche expliziten Deklarationen von Eingangs- und Ausgangskorrelationen sind für jeden Thread-Block 104 mit seiner jeweiligen Eingangsnutzlast 102 und der jeweiligen Ausgangsnutzlast 106 vorhanden.
  • 5 zeigt, dass solche Definitionen in einer Ausführungsform verwendet werden, um es dem System zu ermöglichen, Thread-Blöcke 104 in einer sehr effizienten Pipeline zu planen. Eine gut definierte Ein- und Ausgabe ermöglicht die Synchronisierung auf Objektebene und macht die Synchronisierung nicht zugehöriger Arbeiten überflüssig. Solche wohldefinierten Eingabe- und Ausgabedeklarationen erhöhen die Auslastung und ermöglichen, dass Ressourcen vor dem Kernel-Start (wie durch den „Erfassen“-Pfeil angezeigt) konservativ erfasst und vor Abschluss der Ausführung (wie durch den „Freigabe“-Pfeil angezeigt) programmgesteuert freigegeben werden. 5 zeigt, dass der Scheduler in einer Ausführungsform vor dem Start des Thread-Blocks eine Ressourcenakquisition durchführt (d. h. Dekrementieren des SF-Semaphors um einen bekannten Betrag, der durch den Thread-Block vordeklariert wurde, um die Größe der Ausgangsnutzlasten widerzuspiegeln, um dadurch die für den Thread-Block benötigte Ressourcenmenge zu reservieren), wohingegen der Thread-Block (Anwendung) selbst die Ressource programmgesteuert freigeben kann, nachdem er damit fertig ist und bevor seine Ausführung beendet ist, wobei der Scheduler eine solche Freigabe feststellt und um einen angemessenen programmgesteuert berechenbaren Betrag verfolgt - um eine Garantie für Blockadefreiheit zu bieten, Kontextwechsel zu vermeiden und zusätzliche Flexibilität zu ermöglichen. In einer Ausführungsform kann die Freigabe irgendwo innerhalb des Programmflusses durchgeführt werden und kann inkrementell zu unterschiedlichen Zeiten für einen gegebenen Thread-Block durchgeführt werden, um es dem Thread-Block zu ermöglichen, seine Ressourcenreservierung zu reduzieren, wenn er nicht mehr so viel von der Ressource benötigt. In solchen Ausführungsformen ist es wie bei einer Gruppe von Gästen, die ihre Mahlzeit im Restaurant beendet haben und ihren Tisch verlassen, Sache des Thread-Blocks, zu entscheiden, wann die Ressource freigegeben wird; der systembasierte Scheduler wird die Freigabe erkennen und nutzen, indem er die freigegebene Menge reserviert. Die aggregierte Aktion, wie viel von einer Ressource erworben und wie viel von der Ressource freigegeben wurde, sollte konsistent sein, um sicherzustellen, dass alles erworbene schließlich freigegeben wird, wodurch kumulative Fehler und damit verbundene Blockaden und Unterbrechungen des Vorwärtsfortschritts vermieden werden. Jedoch kann in einer Ausführungsform durch den Thread-Block programmgesteuert bestimmt werden, wann und wie die Ressourcen erworben und freigegeben werden, dies aber durch den systembasierten Scheduler überwacht, erzwungen und ausgenutzt werden.
  • 5 zeigt beispielsweise einige abstrakte Eingaberessourcen 107 und Ausgaberessourcen 108 (z. B. On-Chip-Speicher, eine Hauptspeicherzuweisung, die das System verwendet, um Daten-Marshalling für den Thread-Block 104 zu implementieren, Hardwareressourcen, Rechenressourcen, Netzwerkbandbreite usw.). In einer Ausführungsform sind die Größe/der Umfang solcher Zuweisungen von Eingabe- und Ausgaberessourcen 107, 108 festgelegt, d. h. eine begrenzte Anzahl von Bytes im Fall von Speicherzuweisungen. Da das System die Größen der Eingaben und Ausgaben 102, 106 jedes einzelnen Thread-Blocks 104 kennt, kann es berechnen, wie viele Thread-Blöcke parallel ausgeführt werden können, und Starts von Thread-Blöcken basierend darauf planen, ob sie Erzeuger oder Verbraucher sind. Wenn beispielsweise zwei Thread-Blöcke 104a, 104b an einer Art Erzeuger/Verbraucher-Beziehung teilnehmen, kann das System den Erzeuger einplanen und wissen, welche Ausgangsressource 108 der Erzeuger verwenden wird, und kann dann die Beschaffung des Verbraucher-Thread-Blocks von dieser Ausgangsressource einplanen. Indem es die Größen der Eingangsnutzlast 120 und der Ausgangsnutzlast 106 kennt, kann das System die Pipeline unter Verwendung einer optimalen ressourcenbeschränkten Planung korrekt planen. Siehe z. B. Somasundaram et al., Node Allocation In Grid Computing Using Optimal Resource Constraint (ORC) Scheduling, IJCSNS International Journal of Computer Science and Network Security, Bd. 8 Nr. 6 (Juni 2008).
  • Während der gebräuchlichste Parameter in Bezug auf Mengen von Eingabe- und Ausgaberessourcen 107, 108 die Speichergröße sein wird, sind die Ausführungsformen nicht darauf beschränkt. Die Eingabe- und Ausgaberessourcen 107, 108 können beispielsweise Netzwerkbandbreite, Kommunikationsbusbandbreite, Berechnungszyklen, Hardwarezuweisungen, Ausführungspriorität, Zugriff auf Eingabe- oder Ausgabegeräte wie Sensoren oder Displays oder jede andere gemeinsam genutzte Systemressource sein. Wenn beispielsweise mehrere Thread-Blöcke 104 eine begrenzte Menge an Netzwerkbandbreite gemeinsam nutzen müssen, kann eine ähnliche ressourcenbeschränkte Planung in Bezug auf die Netzwerkbandbreite als Ressourcenbeschränkung gelten. Jede Thread-Sammlung oder jeder Block 104 würde angeben, wie viel Bandbreite er pro Aufruf verwendet, wodurch es dem System ermöglicht wird, innerhalb der Bandbreitenbeschränkung zu planen. In solchen Fällen würde ein Wert oder eine andere Metrik verwendet werden, um die Menge an erforderlicher Netzwerkbandbreite anzugeben (d. h. wie viel der Netzwerkbandbreitenressource durch den Thread-Block beim Aufruf belegt wird). Die Menge an Parallelität, die die GPU unterstützen kann, hängt davon ab, wie groß die Ressourcen sind, die zum Unterstützen des Thread-Blocks 104 benötigt werden. Sobald das System die Größen/Mengen der benötigten Ressourcen kennt, kann das System die Rechenpipeline optimal planen, darunter auch, welche Thread-Blöcke 104 gleichzeitig ausgeführt werden, und die Eingabe-/Ausgaberessourcen zuweisen, bevor die Erzeuger und Verbraucher starten. In einer Ausführungsform ermöglicht es das System, vor dem Starten eines Thread-Blocks Platz in der Ausgangsressource 108 zu erwerben und verfolgt die Nutzung entsprechend. Solche Systemoperationen werden in einer beispielhaften nicht einschränkenden Ausführungsform aus Gründen der Geschwindigkeit und Effizienz durch programmierbare Hardwareschaltungen (z. B. Hardwarezähler und zugehörige Logikgatter, die Sätze oder Pools von freien und Freigabe-Zähler/Semaphor-Paaren implementieren) durchgeführt. Solche programmierbaren Hardwareschaltkreise können durch Systemsoftware und durch auf dem System laufende Anwendungen unter Verwendung herkömmlicher API-Aufrufe programmiert werden.
  • 6 zeigt eine beispielhafte Ansicht einer ressourcenbeschränkten Planung unter Verwendung von Semaphoren SF und SR, die freie und bereite Kapazitäten einer beschränkten Ressource anzeigen. SF kann die Gesamtkapazität der Ressource und SR kann angeben, wie viel Ressourcenkapazität bereits zugeteilt oder anderweitig angefordert wurde. In Kenntnis dieser Werte kann das System berechnen oder anderweitig bestimmen, wie viele (und welche) Thread-Blöcke gestartet werden sollen, um eine Überlastung der Ressource zu vermeiden und in einigen Ausführungsformen die Ressourcennutzung zu optimieren.
  • Ein Erzeuger 110 und ein Verbraucher 112 sind durch eine Ressource 114 verbunden gezeigt. Die Ressource 114 kann ein Softwarekonstrukt sein, wie etwa eine Warteschlange. Jeder Kernel definiert eine Ein- und Ausgabe mit fester Größe - die Synchronisation erfolgt im Objektbereich. Genauer gesagt definiert jeder Kernel technisch eine maximale Ein- oder Ausgabe; Erzeuger können bis zu dieser Menge produzieren. Verbraucher werden möglicherweise (in Koaleszenzstartfällen) mit weniger als der maximalen Anzahl von Arbeitselementen gestartet. Das System kann davon ausgehen, dass der Erzeuger 110 und der Verbraucher 112 immer vollständig ausgeführt werden, und der Hardware- und/oder Software-Planungsmechanismus des Systems kann Systemoperationen überwachen und basierend auf der Überwachung SF und SR warten, aktualisieren und betrachten, um zu bestimmen, wie viele Thread-Blöcke gestartet werden sollen. In einer Ausführungsform verwendet das System die Semaphore, um zu garantieren, dass die Ein-/Ausgabe-Ressourcen verfügbar sind, wenn gleichzeitig laufende Prozesse diese Ressource benötigen, wodurch sichergestellt wird, dass die Prozesse bis zum Abschluss ausgeführt werden können, statt dass die Prozesse festgefahren, ihnen vorgegriffen wird oder sie angehalten werden müssen und es erforderlich ist zu warten, bis die Ressourcen verfügbar werden, oder ein teurer Kontextwechsel mit zugehörigem Aufwand erforderlich ist.
  • In einer Implementierung arbeitet ein systembasierter Hardware- und/oder Software-Scheduling-Agent, -Mechanismus oder -Prozess im Hintergrund unabhängig von Verbrauchern und Erzeugern. Der Scheduling-Agent, - Mechanismus oder -Prozess betrachtet die Semaphore SF und SR, um zu entscheiden, wie viele Erzeuger und Verbraucher das System zu einem gegebenen Zeitschritt starten kann. Zum Beispiel kann der Scheduling-Agent, - Mechanismus oder -Prozess bestimmen, Erzeuger nur dann zu starten, wenn freier Speicherplatz verfügbar ist, und bestimmt basierend auf dem Wert des Freiraum-Semaphors SF, wie viele Erzeuger gestartet werden können. Der Scheduling-Agent, -Mechanismus oder -Prozess bestimmt auf ähnliche Weise basierend auf dem Bereitschaftssemaphor SR die Anzahl gültiger Verbrauchereinträge für die eingeschränkte Ressource. Der Scheduling-Agent, - Mechanismus oder -Prozess aktualisiert die Semaphore, wann immer neue Thread-Blöcke gestartet werden, und überwacht auch Zustandsänderungen, wann immer Thread-Blöcke die Semaphore aktualisieren, bevor sie abgeschlossen und beendet werden.
  • In vielen Implementierungen laufen mehrere Erzeuger und Verbraucher gleichzeitig. Da in solchen Fällen die Ein-/Ausgabe-Ressourcen erworben werden, wenn die Erzeuger und Verbraucher starten, werden die Ein-/Ausgabe-Ressource(n) nicht sauber in belegten Raum und nicht belegten Raum unterteilt. Stattdessen gibt es einen Bruchteil dieser Ressource im Zwischenraum. Zum Beispiel haben Erzeuger, die gerade mit dem Laufen begonnen haben, noch keine gültige Ausgabe erzeugt, so dass das Bereitschaftssemaphor SR die Ausgabe des Erzeugers nicht als gültige Daten registriert und der Wert des Semaphors kleiner als die Menge an Speicherplatz ist, die der Erzeuger schließlich benötigen wird, wenn er gültige Daten ausgibt. In einer Ausführungsform berücksichtigt der Erzeuger diese tatsächliche Datenverwendung nur dann, wenn die vom Erzeuger ausgegebenen Daten gültig werden, indem er das Bereitschaftssemaphor SR inkrementiert. Beispielhafte Ausführungsformen verwenden zwei Semaphore SF und SR, um diese zeitliche Abfolge von Ereignissen zu berücksichtigen, die mit gleichzeitiger Verarbeitung und Ressourcenerfassung zur Startzeit verbunden sind. Zum Beispiel reserviert das System vor dem Starten eines Thread-Blocks Ausgabeplatz, der von dem Thread-Block in der E/A-Ressource 114 benötigt wird, wodurch garantiert wird, dass der Platz verfügbar ist, wenn er benötigt wird, und Blockadebedingungen vermieden werden, die sich aus dem späteren Erwerb der Ressource während der Ausführung ergeben können. Es verfolgt diese Ressourcenreservierung durch Ausleihen vom freien Semaphor SF. Sobald der Thread-Block startet und beginnt, die Ressource zu füllen oder anderweitig zu verwenden, wird die Menge der verwendeten Ressource in den Bereitschaftszustand versetzt - was durch die Aktualisierung des Semaphors SR verfolgt wird. Die Zuweisung von Ressourcen vor dem Start vermeidet nicht nur potenzielle Blockaden, sondern hat auch den Vorteil, dass Algorithmen verwendet werden können, die nicht mit der Möglichkeit umgehen müssen, dass Ressourcen nicht verfügbar sind. Diese potentiell große Vereinfachung der Zuordnungsphase von Daten-Marshalling-Algorithmen ist ein Vorteil.
  • Eine ähnliche Analyse gilt für die Verbraucherseite der Ressourcenzuteilung. Bevor das System einen Verbraucher-Thread-Block startet, prüft es das Bereitschaftssemaphor SR, um sicherzustellen, dass es nicht Null ist. Wenn das System den Verbraucher-Thread-Block startet, verfolgt es, dass der Verbraucher die Ressource in der Zukunft verbrauchen wird, dies aber noch nicht getan hat, indem es das Bereitschaftssemaphor SR dekrementiert. Erst nachdem der Verbraucher die reservierte Ressource verbraucht hat, kann der Systemzustand die Ressource in freien Speicherplatz überführen, die mit der Arbeitsaufgabe verknüpften Ressourcen freigeben (was in beispielhaften Ausführungsformen durch den Verbraucher selbst erfolgt) und das Freiraum-Semaphor SF inkrementieren. Nach der Reservierung und vor der Freigabe befindet sich das Arbeitselement in einem unbestimmten Zustand.
  • In einer Ausführungsform kann der Scheduling-Agent, -Mechanismus oder -Prozess einfach sein, weil er wie oben erläutert Ressourcen unter Verwendung von zwei Semaphoren verfolgt. In beispielhaften Implementierungen können die Semaphore SF, SR durch eine Sammlung von Hardwareschaltungen wie Registern und/oder Zählern implementiert werden, die kostengünstig zu warten, zu aktualisieren und zu verwenden sind. Bei jedem Zyklus oder mit einer anderen periodischen oder nicht periodischen Frequenz aktualisiert das System die Register/Zähler durch einfache und kostengünstige Hardware-basierte Aktualisierungen (z. B. Inkrementieren und Dekrementieren, Addieren oder Subtrahieren ganzzahliger Werte zu/von ihnen oder dergleichen), um den Ressourcenverbrauch zu berücksichtigen. Darüber hinaus können solche Implementierungen direkt auf Legacy-GPU-Scheduling-Implementierungen abgebildet werden (die aufgrund der Einfachheit der aktuellen Scheduling-Techniken nicht die gesamte Komplexität des Legacy-Schedulers erfordern), sodass kein zusätzlicher Hardwareentwurf erforderlich ist. In anderen Implementierungen können zusätzliche vereinfachte Hardware-Schaltungen, die dem Strom-Scheduler zugeordnet sind, bereitgestellt werden, wodurch reduzierte Chipflächen- und Leistungsanforderungen erreicht werden. Da der aktuelle Scheduler in einer abstrahierten Weise um einfache Zähler implementiert werden kann, die die Ressourcenauslastung verfolgen, kann ein einfacher Scheduler implementiert werden. Die Semaphorwerte können über Hardware- oder Softwaremechanismen aktualisiert werden. Wenn Softwareanweisungen verwendet werden, können die Anweisungen im Systemcode oder Anwendungscode enthalten sein. In einer Ausführungsform werden Signale zum Anfordern und Freigeben von Ressourcenreservierungen von den Erzeuger- und Verbraucher-Thread-Blöcken selbst bereitgestellt. Zusätzlich kann die Erhöhung/Verringerung von SF und SR programmgesteuert als Reaktion auf die Anforderungs- und Freigabesignale von den Erzeugern und Verbrauchern durchgeführt werden, um eine frühe Ressourcenfreigabe auszunutzen. Auch wenn SF und SR als Teil des Schedulers angesehen werden können, der diese Werte letztendlich steuert, können übergeordnete Systemkomponenten zusätzlich dafür sorgen, dass schlecht programmierte Erzeuger und Verbraucher keine Ressourcen in Anspruch nehmen oder den Fortschritt stoppen können.
  • Es werden genügend solche Register bereitgestellt, um die maximale Anzahl von Aufgaben zu unterstützen, die für eine gleichzeitige Verarbeitung benötigt werden, d. h. um die Anzahl von Zuständen darzustellen, die benötigt werden, um alle Verbraucher und Erzeuger zu unterstützen, die gleichzeitig gestartet werden können. In einer Ausführungsform bedeutet dies, dass ein Paar von Semaphoren für alle gleichzeitig ausgeführten Thread-Blöcke oder Anwendungen bereitgestellt wird. Der Scheduler kann eine beliebige Anzahl gleichzeitiger Verbraucher- und Erzeugerknoten auf optimierte Weise starten, wobei die Zustandsmenge, die der Scheduler aufrechterhalten muss, um die Ressourcenreservierung und -nutzung zu verfolgen, nicht von der Anzahl der gleichzeitig ausgeführten Thread-Gruppen von der gleichen Aufgabe/einem gleichen Knoten abhängt. Vielmehr wächst die Zustandsmenge, die der Scheduler für einen gegebenen Knoten in einer Ausführungsform aufrechterhält, nicht mit und ist somit nicht abhängig von der Anzahl der in der Warteschlange befindlichen Arbeitsaufgaben oder Aufgaben (z. B. Threads), die darauf warten, ausgeführt zu werden. Die Anzahl der Zustände, die der Scheduler verwaltet, wächst mit der Anzahl der zuzuweisenden Ressourcen und mit der Anzahl der im System aktiven Shader-Programme (Tasks), die in einem Pipeline-Planungsmodell von der Anzahl der Stufen in der Pipeline abhängen - - da die Ausgangsressource einer Stufe im Allgemeinen die Eingangsressource einer nachfolgenden Stufe in der Pipeline umfasst. In einer Ausführungsform unterhält der Scheduler ein Register pro „Ressource“ (z. B. Speicher, Cache usw.), um SF darzustellen, und ein Register pro „Aufgabe“, um SR darzustellen.
  • Die Technologie hierin ist jedoch nicht auf das Erstellen von Pipelines beschränkt, sondern kann stattdessen kompliziertere Beziehungen und Abhängigkeiten unterstützen. Die Zustandsmenge, die der Scheduler aufrechterhalten muss, hängt in solchen Fällen von der Topologie des Knotengraphen ab, der mit der Planung für die gleichzeitige Ausführung beauftragt ist. Da, wie oben besprochen, der Scheduler in einigen Implementierungen einfach und effizient basierend auf nur zwei Werten SF, SR pro Ressource wie oben beschrieben ausgelegt ist, werden Graphen beliebiger Komplexität/Topologie möglicherweise nicht unterstützt, und ein anderer Scheduling-Algorithmus/eine andere Anordnung kann in Kontexten aufgerufen werden, in denen eine solche Flexibilität auf Kosten einer erhöhten Scheduling-Komplexität erforderlich ist.
  • Darüber hinaus ist der Scheduler in Fällen, in denen die zuzuweisende Ressource Speicher ist, nicht auf irgendeinen Speichertyp beschränkt, sondern kann vielmehr mit vielen verschiedenen Speicherstrukturen wie linearen Speicherpuffern, Stapeln, assoziativen Caches und vielen mehr verwendet werden.
  • Da die Anzahl der Zustände, die der Scheduler der beispielhaften Ausführungsform aufrechterhält, eine feste Größe hat, um den Scheduler einfach zu halten, ergibt sich ein Phänomen, das wir Backpressure nennen. Erstens kann in beispielhaften Ausführungsformen die Beschränkung auf feste Größe die Verwendung von nur einem Paar von Semaphoren SF, SR pro Ressource beinhalten, um die Zuweisung und Freigabe von Ressourcen und somit die Parallelität des Systems zu steuern. In einer Ausführungsform gibt es nur zwei Werte pro Ressource, so dass die Zustandsmenge, die der Scheduler aufrechterhält, nicht mit der Art des Graphen der Ausführungsknotentopologie wächst, die der Scheduler planen soll. In beispielhaften Ausführungsformen gibt es ein Paar solcher Semaphore pro Ressource, und in einem Graphen mit mehreren Knoten und Warteschlangen, die diese verbinden, gibt es ein Paar Semaphore pro Warteschlange. Bei der Initialisierung dieser Werte SF, SR zu Beginn der Systemausführung werden sie auf die Menge an Ressourcen initialisiert, die diesen bestimmten Stufen der Pipeline- oder Graphentopologie zur Verfügung stehen. Die Semaphore SF, SR ändern sich dann (erhöhen und verringern sich), wenn Arbeit geplant wird.
  • Wenn eine Ressource zur Neige geht, wird der bestimmte Knoten, der diese Ressource benötigt, nicht mehr geplant, und ein anderer Knoten beginnt mit der Ausführung, da er über verfügbare Ressourcen und Eingaben verfügt.
  • In einer Ausführungsform werden beim Starten der Arbeit die freien und Bereitschaftssemaphore SF, SR atomar mit diesem Arbeitsprotokoll modifiziert. Zum Beispiel dekrementiert das Starten von Arbeit das freie Semaphor SF atomar, wodurch verhindert wird, dass andere Arbeit unter der irrtümlichen Ansicht gestartet wird, dass zusätzliche Ressourcen verfügbar sind, wenn diese Ressourcen tatsächlich bereits reserviert wurden. Das wäre ein bisschen so, als würde ein Maitre d' die Anzahl der Restaurantbesucher verfolgen, die bereits in der Bar etwas trinken, bevor sie Platz nehmen, um sicherzustellen, dass verfügbare Tische ihnen und nicht neu angekommenen Gästen zugewiesen werden. Dies vermeidet die Möglichkeit eines Wettlaufs. In ähnlicher Weise dekrementiert der Scheduler das freie Semaphor SF atomar, um einem Erzeuger Ressourcen zuzuweisen. Darüber hinaus kann die Anwendung die Semaphore verwenden, um in einigen Ausführungsformen Ressourcen vor Abschluss der Arbeit freizugeben. Somit erfolgt in beispielhaften, nicht einschränkenden Ausführungsformen die Ressourcenreservierung durch einen Scheduler, die Ressourcenfreigabe jedoch durch den Anwendungs-/Benutzercode.
  • 7 und 8 zeigen zusammen ein Beispiel einer Eins-zu-Eins-Zuordnung zwischen Ressourcenbeschaffungsereignissen und Ressourcenfreigabeereignissen. Die Zeit läuft von links nach rechts. Angenommen, die Ressource ist ein Puffer im Speicher. Wie 7 zeigt, wird SF bei der Erfassung von ("-- SF) um einen Betrag subtrahiert, der durch eine explizite Definition aus dem Erzeuger-Thread-Block deklariert wird, um anzuzeigen, dass dieser Bruchteil oder diese Menge des Speichers zur Verwendung reserviert ist. 8 zeigt, dass der Erzeuger-Thread-Block SR irgendwann in seiner Lebensdauer inkrementieren wird, um anzuzeigen, dass der Erzeuger-Thread-Block die Ressource jetzt tatsächlich verwendet, um gültige Daten zu speichern. Da die vom Verbraucher-Thread-Block benötigten Daten nun gültig sind, kann der Scheduler den Verbraucher-Thread-Block starten. Der Scheduler verringert auch SR beim Starten des Verbrauchers - wodurch die Symmetrie zwischen den beiden Semaphoren und Erzeuger/Verbraucher-Tasks vervollständigt wird. Irgendwann während seiner Ausführung kann der Verbraucher, wenn er die Ressource verbraucht, dem System mitteilen, dass er diese Ressource nicht mehr benötigt. Das System überführt somit die Ressource als Reaktion auf ein Freigabeereignis, das durch den Anwendungs-/Verbrauchercode durchgeführt wird, in freien Speicherplatz, indem es den SF-Wert hinzufügt, was bedeutet, dass der Scheduler nun einen oder mehrere zusätzliche Erzeuger starten kann. Wie in 13 gezeigt, startet der Scheduler diesen weiteren Erzeuger erst, wenn der zuvor gestartete Erzeuger den für ihn reservierten Speicher freigibt; die nächste Erfassung kann daher nur erfolgen, nachdem der Scheduler den SF-Wert inkrementiert hat, um anzuzeigen, dass die Ressourcenmenge nun für eine erneute Erfassung verfügbar ist. Die Parallelität im System wird folglich durch die Auslastungsddauer der Ressourcennutzung begrenzt.
  • 9 ist ein Flussdiagramm einer beispielhaften Scheduler-Ansicht von Operationen, die den Start eines Thread-Blocks einleitet, je nachdem, ob die Eingabe bereit und die Ausgabe verfügbar ist, wie durch SR > 0 und SF > 0 angegeben. Eine solche Funktionalität kann in einer Ausführungsform in Hardware implementiert werden. Es können mehrere Sätze von Hardwareschaltkreisregistern bereitgestellt werden, wobei jeder Registersatz einer Aufgabe entspricht. Wie rechts in 9 gezeigt, enthält jeder Registersatz (der als „Aufgabenbeschreibung“ bezeichnet werden kann) beispielsweise:
    • einen Verweis auf eine Aufgabe (z. B. einen Namen oder eine Adresse, die zum Aufrufen einer Instanz der Aufgabe verwendet werden kann);
    • ein SR-Semaphor (das der Aufgabe eindeutig zugeordnet ist); und
    • einen Verweis auf mindestens ein SF -Semaphor (*SF) (einige Ausführungsformen erlauben mehrere aufgabenfreie Semaphor-Verweise, um auf ein gemeinsames freies Semaphor SF zu verweisen; andere Ausführungsformen könnten das freie Semaphor auch nach Wert statt nach Verweis mit der Aufgabenkennung speichern).
  • Mehrere Tasks können auf das/die gleiche(n) Semaphor(e) verweisen, wodurch implizite Abhängigkeiten zwischen Tasks implementiert werden können.
  • Bei jeder Zeiteinheit bzw. jedem Takt betrachtet der Scheduler diese Semaphore und vergleicht sie mit Null. Wenn die Semaphore für eine Aufgabe beide größer als Null sind, bestimmt der Scheduler, dass er die Task starten kann, und tut dies, indem er das SF-Semaphor der Aufgabe beim Startdekrementiert. Wenn die Aufgabe die Verwendung der Ressource beendet hat, veranlasst die Aufgabe selbst (in einer Ausführungsform) die Hardware, die SF- und SR-Semaphore zu inkrementieren, indem sie einen Mechanismus zum Erkennen des zu inkrementierenden Semaphors zu verwendet. Im Falle des Bereitschaftssemaphors kann die Aufgabe ein Inkrementsignal an den der Aufgabe zugeordneten Aufgabeneintrag senden. Im Fall des freien Semaphors sendet die Software ein Inkrementsignal mit einem Index in die Tabelle der freien Semaphore. Software kann auf die Semaphore mit Namen verweisen und ihnen namentlich das Inkrementieren befehlen. Es versteht sich, dass die Signale oder Befehle „Inkrementieren“ und „Dekrementieren“ tatsächlich eine Erhöhung (Addition) oder Verringerung (Subtraktion) um eine beliebige ganze Zahl innerhalb eines Bereichs befehlen können.
  • Auf der Software-API-Ebene umfassen Objekte, die von einem Entwickler oder Anwendungsprogrammierer definiert oder deklariert und von Systemsoftware bedient werden können:
    • mindestens ein Warteschlangenobjekt und
    • ein Aufgabenobjekt, das sowohl auf den auszuführenden Code als auch auf das zu verwendende Warteschlangenobjekt verweist.
    • Das System ordnet dann die Warteschlangen Semaphoren und die Aufgaben Hardware-Aufgabendeskriptoren zu.
  • Ein Anwendungsprogramm spezifiziert zunächst den Graphen, d. h. die Topologie der auszuführenden Aufgabenknoten und ihre Abhängigkeiten. Als Reaktion auf eine solche Spezifikation erstellt die Systemsoftware die Warteschlangen und initialisiert die Hardware und das System. Wenn die Anwendung die Ausführung des Graphen auslöst, ruft die GPU-Systemsoftware die Root-Task(s) des Graphen auf und beginnt mit der Ausführung des Graphen auf autonome Weise, die von der CPU entkoppelt ist. Siehe 9A. Das System kann feststellen, dass ein Graph fertig ist, wenn alle Warteschlangen geleert sind und die Graphenausführung im Leerlauf ist. Eine Alternative könnte ein vom System interpretiertes Token verwenden, um explizit das Ende der Arbeit anzuzeigen. 9A zeigt drei alternative Wege für die Freigabe von Ressourcen: Option 1) Arbeitsende-Token, das durch die Pipeline weitergegeben wird, um die erledigte Arbeit zu bezeichnen; Option 2) Warten, bis die Warteschlangen leer sind und alle aktiv ausgeführten Knoten aufhören zu laufen; Option 3) Benutzercode in der Aufgabe bestimmt wann erledigt und signalisiert (das häufigste Szenario in beispielhaften Ausführungsformen).
  • 10 zeigt eine beispielhafte ressourcenbeschränkte Planung unter Verwendung einer Warteschlange. Wie oben erwähnt, kann die Ressource alles sein, darunter jede Art von Speicherstruktur, aber oft ist es vorteilhaft, eine Warteschlange zu verwenden, um Daten von einem Erzeuger zu einem Verbraucher zu übergeben - ähnlich dem Modell, das häufig in Grafik-Pipelines verwendet wird. In einigen Ausführungsformen sind die Semaphore und die Testlogik in Hardwareschaltkreisen implementiert, während die Warteschlange ein Softwarekonstrukt ist und durch Systemsoftware verwaltet wird.
  • 11 zeigt, wie ein oder mehrere Erzeuger gleichzeitig in eine Warteschlange schreiben können, wenn ein oder mehrere Verbraucher Daten aus der gleichen Warteschlange lesen. Die Warteschlange kann somit einen erzeugenden Abschnitt, einen bereiten Abschnitt und einen verbrauchenden Abschnitt enthalten. Der erzeugende Abschnitt enthält gültige Daten, die gerade von einem Erzeuger geschrieben werden, der bereite Abschnitt enthält gültige Daten, die der Erzeuger zuvor in die Warteschlange geschrieben hat und die noch nicht begonnen haben, vom Verbraucher konsumiert zu werden, und der verbrauchende Abschnitt kann gültige Daten enthalten, die zuvor vom Erzeuger geschrieben wurden und gerade vom Verbraucher gelesen werden.
  • 12 zeigt, wie ein beispielhafter Scheduler das Daten-Marshalling mit einer Warteschlange implementieren kann. In diesem Beispiel verfolgt das SF-Semaphor, wie viele freie Slots es in der Warteschlange gibt, und das SR-Semaphor verfolgt, wie viele fertige Slots (d. h. Slots, die gültige Daten enthalten, die noch nicht vom Verbraucher freigegeben wurden) sich in der Warteschlange befinden. Der Scheduler verwendet diese beiden Semaphore, um zu bestimmen, ob (wann) neue Erzeuger und neue Verbraucher gestartet werden sollen. Unten in 12 sind vier Zeiger gezeigt: Äußerer Put, Innerer Put, Innerer Get und Äußerer Get. Die Systemsoftware kann diese vier Zeiger zum Verwalten der Warteschlange verwenden. Während die Semaphore oben und die Zeiger unten das Gleiche zu verfolgen scheinen, werden die Semaphore in einigen Ausführungsformen durch Scheduling-Hardwareschaltkreise gepflegt und aktualisiert, während unten dargestellten die Zeiger durch Anwendungssoftware gepflegt und aktualisiert werden. Ein derartiges Entkoppeln der Semaphor-Scheduling-Funktionen von den Warteschlangenverwaltungsfunktionen bietet bestimmte Vorteile, darunter die Ermöglichung einer Vielzahl von Anwendungsfällen. Betrachtet man zum Beispiel 23, können die SR-Semaphore für zwei verschiedene Erzeuger um unterschiedliche Beträge inkrementiert werden. In einer Ausführungsform betrachtet der Scheduler nur diese Semaphore, um zu entscheiden, wie viele Verbraucher zu starten sind. Daher gibt es in diesem Beispiel keine Eins-zu-Eins-Entsprechung zwischen Erzeugern und Verbrauchern, und das Ergebnis ist eine Arbeitsverstärkung, die mehrere Verbraucher (mehrere Instanzen der gleichen Aufgabe oder unterschiedlicher Aufgaben oder beides) pro Eintrag startet. Dies kann zum Handhaben größerer Ausgabegrößen verwendet werden. Pro Eintrag kann eine beliebige Anzahl von Verbrauchern gestartet werden, wobei alle Verbraucher an ihren Eingängen die gleiche Nutzlast „sehen“. Die Verbraucher koordinieren sich untereinander, um die Warteschlangenzeiger voranzutreiben, welche die Warteschlange selbst verwalten. Solche parallelen Datenoperationen können verwendet werden, um es unterschiedlichen Verbrauchern zu ermöglichen, unterschiedliche Arbeiten an den Eingabedaten auszuführen, oder um die gleiche Arbeit an unterschiedlichen Teilen der Eingabedaten auszuführen, oder allgemeiner, um die gleiche oder unterschiedliche Arbeit an den gleichen oder unterschiedlichen Teilen der Eingabedaten auszuführen. Diese Funktionalität wird ermöglicht, indem die Verwaltung des Zustands der Warteschlange von der neuen Arbeitsplanungsfunktion entkoppelt wird, die durch Semaphore bereitgestellt wird.
  • 13 und 14 zeigen, dass der Erzeuger in einigen Ausführungsformen die Ressource früher freigeben kann, wenn er die Ressource doch nicht benötigt. Angenommen, ein Erzeuger wird gestartet, der bedingt eine Ausgabe generiert. Vor dem Start gibt der Erzeuger die Menge der Ressource an, die er benötigt, wenn er eine Ausgabe erzeugt, und der Scheduler handhabt dies, indem er von SF die Menge der Ressource subtrahiert, die der Erzeuger für benötigt erklärt, wodurch garantiert wird, dass der Erzeuger bis zur Fertigstellung laufen kann und einen anderen Erzeuger daran zu hindern, um diese Ressource zu konkurrieren. Wenn der Erzeuger jedoch während der Ausführung und vor der Fertigstellung feststellt, dass er einige oder alle dieser Ressourcen nicht mehr benötigt (z. B. weil er feststellt, dass er weniger oder keine Ausgabe erzeugen wird), kann der Erzeuger dies dem System-Scheduler anzeigen, indem er seine Reservierung der Ressource freigibt. Die Ressourcenlebensdauer ist jetzt viel kürzer, und die Gleichzeitigkeit des Systems kann mit verringerter Latenzzeit zwischen der Freigabe der Ressource und dem Start des nächsten Erzeugers zunehmen. Dies wird durch die Bewegung des zweiten Erzeugers in 14 nach links in der Figur im Vergleich zu seiner Position in 13 angezeigt. Insbesondere wird der erste Erzeuger SF entsprechend erhöhen, was es dem Scheduler ermöglicht, sofort einem zweiten Erzeuger zu gestatten, die Ressource zu erwerben, so dass der Scheduler SF wieder verringert, um die Reservierung für diesen zweiten Erzeuger zu notieren.
  • Darüber hinaus können die Freigaben vom Erzeuger, Verbraucher oder sogar späteren Stadien in der Pipeline herausgegeben werden. 15 zeigt eine Pipeline aus drei Stufen, wobei die endgültige Freigabeoperation durch den Enkel des Erzeugers durchgeführt wird (d. h. eine Pipeline-Stufe stromabwärts in der Pipeline von der nächstfolgenden Stufe nach dem Erzeuger in der Pipeline-Sequenz). Somit kann eine Ressourcenreservierung über mehrere Pipeline-Stufen aufrechterhalten werden, solange der Scheduler eine konsistente Erfassung und Freigabe erzwingt (d. h. die Ressourcenreservierungsmenge wird immer durch entsprechende Ressourcenfreigabemengen ausgeglichen).
  • 16-20 zeigen ein weiteres Beispiel, in dem ein Erzeuger die Ressource Stück für Stück freigibt. In 16 erwirbt der Erzeuger N Einheiten der Ressource. Bei der Erzeugung einer Teilausgabe wie in 17 (z. B. hat das System N Slots in einer Speicherressource reserviert und der Erzeuger, aber nur der Erzeuger hat eine Anzahl von Slots im Wert von Daten ausgegeben, die im schraffierten Teil von 17 gezeigt sind, wie etwa im Wert von M-N Slots), kann der Erzeuger ungenutzten Speicherplatz M (18) freigeben, der für die Verwendung durch einen anderen Erzeuger verfügbar wird (20). Nachdem der Erzeuger den Platz M<N freigegeben hat (19), impliziert dies, dass er einige gültige Daten in der Ressource gespeichert hat, aber M Slots nicht benötigt, die der Scheduler für einen anderen Erzeuger reservieren kann, der nun mit der Nutzung des freigegebenen Platzes M beginnen kann (20). In diesem Fall ist dem Erzeuger klar, dass N Slots für ihn reserviert wurden, und er hat nur M Slots verwendet (wie ein Restaurant, das einen Tisch für 8 reserviert, aber nur 6 erscheinen). In diesem Fall einer teilweisen Freigabe wird der Verbraucher darüber informiert, dass er nur N gültige Slots lesen kann (19), sodass der Verbraucher wie in 20 gezeigt einen Teil der Ausgabe liest und dann freigibt (SF += N - M) und der andere Teil M der Zuteilung von einem anderen Erzeugern erworben wird. Die Semaphore SF, SR können somit zum Anzeigen eines Bruchteils der Ressourcennutzung verwendet werden, wobei ein Erzeuger den Bruchteil zurückgeben kann, der nicht verwendet wurde. Eine weitere Ressourcenfreigabe von einem unabhängigen Erzeuger/Verbraucher kann gerade rechtzeitig eintreffen, sodass der Scheduler einen anderen Erzeuger starten kann. Dieser Mechanismus ermöglicht die Verarbeitung variabler Ausgaben bis zur maximalen Größe von N.
  • 21 zeigt, dass die Größe der Ressource, deren Nutzung der Scheduler verfolgt, variabel sein kann.
  • Beispiel Cache Footprint Management
  • In einer beispielhaften Ausführungsform kann die Ressource, die vom System-Scheduler erworben und freigegeben wird, den Cache umfassen, und die Semaphore SF, SR verfolgen die Anzahl von Cache-Zeilen, die für den Datenfluss zwischen Erzeugern und Verbrauchern verwendet werden. Da viele Caches so ausgelegt sind, dass sie Cache-Zeilen Speicherstellen frei zuordnen, sind die Speicherstellen oft nicht zusammenhängend und eine Datenfragmentierung innerhalb des Caches ist eher unvorhersehbar. Nichtsdestotrotz kann der Scheduler der offenbarten Ausführungsform die Verwendung des Caches (und des Hauptspeichers) mit einem einzigen Wert SF verfolgen und verwalten, da dieser Wert lediglich angibt, wie viele Cache-Zeilen noch zum Erfassen durch einen Thread-Block verfügbar sind.
  • Wie in 22 gezeigt, verfolgt der Scheduler der nicht einschränkenden Ausführungsform den Cache-Arbeitssatz, bei dem es sich um die schraffierten Cache-Zeilen handelt, die aktiv verwendet werden. Hardware-Caches sind hervorragende Allokatoren, was bedeutet, dass Cache-Zeilen beliebig fragmentiert werden können. Wenn ein Erzeuger über einen vollständig assoziativen Cache in einen externen Speicher schreibt, wird eine Cache-Zeile zugewiesen (in ähnlicher Weise wird keine Cache-Zeile zugewiesen, wenn der Erzeuger nicht in einen Teil des externen Speichers schreibt). In praktischen Implementierungen sind Caches typischerweise satzassoziativ, haben also kein perfektes Verhalten in dieser Hinsicht, kommen ihm aber dennoch recht nahe. Was der System-Scheduler zu tun versucht, ist, eine Annäherung an die Art und Weise zu planen, wie Cache-Zeilen kostengünstig dynamisch zugewiesen werden können.
  • Die Art und Weise, wie der Cache Hauptspeicherzuordnungen von Blöcken mit fester Größe innerhalb des Caches fragmentiert, kann vom Scheduler der offenbarten Ausführungsform ignoriert werden, da Planungsentscheidungen nicht auf der tatsächlichen oder Worst-Case-Nutzung beruhen, sondern auf der Gesamtzahl von Cache-Zeilen, die reserviert/erworben und freigegeben wurden, ohne Rücksicht darauf, wie diese Cache-Zeilen physischen Speicheradressen zugeordnet werden könnten. Dies impliziert, dass die Zuordnung von Cache-Zeilen zu Hauptspeicherblöcken mit fester Größe (ein Vorteil für die Softwareentwicklung ist die Verwendung einer Speicherblockzuordnung mit fester Größe) vom Cache verwaltet werden kann und der System-Scheduler die physische Speichernutzung lediglich auf der Grundlage der Gesamtzahl von Cache-Zeilen verfolgen kann, die für die physische Speicherzuweisung verwendet werden, ohne sich Gedanken darüber machen zu müssen, welche bestimmten Speicherblöcke mit fester Größe zugewiesen werden oder nicht. Beispielsweise können Erzeuger nur teilweise in jeden Chunk der festen Blockspeicherzuordnung schreiben und Verbraucher ihn möglicherweise nur teilweise lesen. Aber der Schedule muss nicht verfolgen, welche Blöcke gelesen oder beschrieben werden oder nicht, da der Cache dies automatisch verfolgt. Die Verwendung des zugeordneten Cache zum Verfolgen der Speicherzuordnung umgeht die Notwendigkeit für den Scheduler, verknüpfte Listen oder andere Mechanismen zu verwenden, die einige andere Scheduler möglicherweise verwenden müssen, um die Fragmentierung von Speicheraktualisierungen durch physischen externen Speicher zu verfolgen. Der beispielhafte Scheduler kann die Fragmentierung ignorieren, indem er zum Verwalten der Fragmentierung vorhandene Cache-Zuweisungsmechanismen verwendet, während er dennoch zulässt, dass der On-GPU-Datenfluss im/durch den On-Chip-Cache verbleibt. Durch die Verwaltung des Cache-Footprints in Chunks mit fester Größe profitiert das System vom On-Chip-Datenfluss, indem es die Fähigkeit des Cache nutzt, einen Datenfluss zu erfassen, der im Vergleich zu einer viel größeren Speicherzuweisung spärlich ist, da der Cache erfasst, was tatsächlich gelesen und geschrieben wird. Der Cache stellt eine begrenzte Arbeitsgröße bereit, die ein Scheduler nutzen kann, wenn der Scheduler seinen Arbeitssatz auf eine begrenzte Größe verwalten kann. Das beispielhafte, nicht einschränkende Planungsmodell ermöglicht dies. Beispielhafte Ausführungsformen können zusätzliche Planungsbeschränkungen aufschichten, die das Caching effizienter machen können.
  • Wenn ein Verbraucher nur das Lesen (im Gegensatz zum Aktualisieren) von Daten aus einer Cache-Zeile beendet, kann es außerdem erforderlich sein, die Cache-Zeile zu zerstören (ungültig zu machen, ohne sie in einen externen Speicher zu verschieben), damit sie freigegeben und an den Scheduler zurückgegeben werden kann, ohne dass die Cache-Zeile wieder in den externen Speicher geschrieben werden muss. Das bedeutet, dass von einem Erzeuger erzeugte Daten durch den On-Chip-Cache zu einem Verbraucher geleitet werden können, ohne sie in einen externen Speicher zu schreiben - das spart Speicherzyklen und Speicherbandbreite und reduziert die Latenz. In der Zwischenzeit verwaltet der Scheduler den Cache aktiv, indem er die Ressourcenbeschränkungsplanung der Cache-Zeilen verwendet, was die Cache-Effizienz erhöht.
  • Verallgemeinernde Funktionen wie Arbeitsverstärkung und Arbeitserweiterung
  • 23 und folgende zeigen beispielhafte, nicht einschränkende Topologien von Ausführungsknotengraphen, die konstruiert werden können, um die offenbarten Scheduler-Ausführungsformen zu verwenden. 23 wurde oben in Verbindung mit 12 beschrieben.
  • 24 zeigt durch Schattierung, dass die gestarteten Verbraucher nicht die gleichen Programme sein müssen. Mehrere Instanzen des gleichen Verbrauchers oder mehrere unterschiedliche Verbraucher (d. h. unterschiedliche Instanzen der gleichen Aufgabe oder unterschiedliche Aufgaben) können gleichzeitig von der gleichen Warteschlange gestartet werden.
  • 25 zeigt ein Beispiel für Arbeitsaggregation, einen Mechanismus, der komplementär zur Arbeitserweiterung ist. Hier reiht ein Erzeuger einige Arbeiten in eine spezielle Warteschlange ein, die Verbraucher nicht sofort starten wird. Vielmehr ist die Warteschlange mit einem Aggregationsfenster programmiert, das es ihr ermöglicht, Arbeit zu gruppieren und gemeinsam zu handhaben, die der Erzeuger innerhalb eines bestimmten Zeitfensters und/oder basierend auf einer bestimmten Menge von Elementen erzeugt, die vom Erzeugeren erzeugt werden. In einem Beispiel versucht die Warteschlange, bis zu einer vom Benutzer angegebenen Anzahl von Arbeitsaufgaben zu sammeln, bevor eine Instanz der Verbraucheraufgabe gestartet wird. Die Warteschlange teilt den gestarteten Verbrauchern auch mit, wie viele Artikel sie sammeln konnte (Minimum = 1, Maximum = benutzerdefinierter Wert). Um dieses Merkmal zu verwenden, würde 9 modifiziert werden, um mit diesem programmierten Wert verglichen zu werden, und SR wird um diesen programmierten Wert inkrementiert. Dieser Anwendungsfall ist beispielsweise nützlich, um Hardwareunterstützung zum Sicherstellen zu verwenden, dass alle Threads in einem Thread-Block Daten zu verarbeiten haben, wenn der Thread-Block gestartet wird.
  • 26 zeigt, was bei einer Zeitüberschreitung geschieht, um die Kohärenz wiederherzustellen. Wenn das Aggregationsfenster von 25 nicht vollständig gefüllt wird, tritt eine Zeitüberschreitung auf, und es erfolgt ein teilweiser Start, um die Latenzzeit zu reduzieren. Bei solchen teilweisen Starts wird das SR-Semaphor um die Anzahl der Elemente dekrementiert, die tatsächlich gestartet wurden, und nicht um den benutzerdefinierten programmierbaren Wert. Das Timeout legt eine Obergrenze dafür fest, wie lange die Warteschlange wartet, bevor Verbraucher gestartet werden.
  • 27 zeigt eine beispielhafte Join-Operation. Die unterschiedlichen Erzeuger 502 stellen unterschiedliche Arbeitsstücke bereit, die versuchen, eine gemeinsame Struktur mit unterschiedlichen Feldern auszufüllen, die den unterschiedlichen Erzeugern entsprechen. Im gezeigten Beispiel schreibt jeder der drei Erzeuger Felder in jeden der Ausgangsdatensätze 508(1), 508(n), wobei jeder Ausgangsdatensatz drei Felder 510(a), 150(b), 510(c) entsprechend den drei Erzeugern 502(a), 502(b), 502(c) enthält. Das heißt, der Datenerzeuger 502(a) schreibt in das Feld 510(a), der Datenerzeuger 502(b) schreibt in das Feld 502(b) und der Datenerzeuger 502(c) schreibt in das Feld 502(c) jedes Ausgangsdatensatzes 508. Jeder Erzeuger 502 hat somit seinen eigenen unabhängigen Platzbegriff im Ausgangspuffer. Jeder Erzeuger 502 hat sein eigenes jeweiliges freies Semaphor SF, das es dem Erzeuger ermöglicht, seine eigenen Felder 510 auszufüllen, solange Platz vorhanden ist. Es gibt somit drei redundante freie Semaphore SFA, SFB und SFC, die sich alle auf die gleichen Ausgangsdatensätze beziehen, aber jeder einen unterschiedlichen Satz von Feldern 510 in diesen Ausgangsdatensätzen verfolgt. Somit bilden diese Semaphore in dieser beispielhaften Ausführungsform eins zu eins die Ressourcenbelegung ab, doch sind andere Anordnungen möglich.
  • Im gezeigten Beispiel ist der letzte Erzeuger 506, der sein entsprechendes letztes Datensatzfeld gefüllt hat, dafür verantwortlich, das Bereitschaftssemaphor SRvorzurücken, um anzuzeigen, dass die Ausgangsdatensätze 508 gültig sind, um von dem Verbraucher gelesen zu werden. Da das Scheduling so einfach ist, können relativ kleine Mengen an Scheduling-Hardware verwendet werden, um eine relativ komplizierte Ausgangsdatenstruktur zu verwalten.
  • 28 zeigt ein Sortieren von Arbeit in mehrere Warteschlangen unter Verwendung von Aggregation, um die Ausführung neu zu konvergieren. Hier gibt ein Erzeuger an drei verschiedene Warteschlangen aus, die Daten an drei verschiedene Verbraucher marshallen. Die hierin beschriebenen Scheduling-Mechanismen gelten für jede der drei Warteschlangen.
  • 29 zeigt ein Beispiel für das Sortieren von Arbeit in mehrere Warteschlangen für die Shader-Spezialisierung, und 30 zeigt das Sortieren von Arbeit, um die Divergenz beim Echtzeit-Raytracing zu verringern. Strahlen können zufällig divergierende Arbeit erzeugen. Durch Anordnen mehrerer Warteschlangen in diesen Topologien zusammen mit Koaleszieren (gezeigt durch größer werdende Elemente an den hinteren Enden der Warteschlange) wird die Kohärenz der Verarbeitung erhöht, um zufällige Divergenzen zu reduzieren. Eine solche Aggregation kann zum Sortieren der Arbeit in kohärente Stapel verwendet werden. Diese Anordnung kann immer dann verwendet werden, wenn es eine Abweichung im System gibt.
  • 31 zeigt ein grundlegendes Abhängigkeitsplanungsmodell, das das Obige verallgemeinert, um auszuwählen, welche von mehreren Aufgaben basierend auf der Abhängigkeit von bereits abgeschlossenen Aufgaben gestartet werden sollen.
  • 32 und 33 zeigen Beispiele dafür, wie diese verallgemeinerten Konzepte verwendet werden können, um Grafikaufgaben und eine Grafik-Pipeline zu implementieren, die ein Grafik-Grid speist.
  • Alle hierin zitierten Patente und Veröffentlichungen sind für alle Zwecke durch Bezugnahme aufgenommen, als wären sie ausdrücklich angegeben.
  • ZITATE ENTHALTEN IN DER BESCHREIBUNG
  • Diese Liste der vom Anmelder aufgeführten Dokumente wurde automatisiert erzeugt und ist ausschließlich zur besseren Information des Lesers aufgenommen. Die Liste ist nicht Bestandteil der deutschen Patent- bzw. Gebrauchsmusteranmeldung. Das DPMA übernimmt keinerlei Haftung für etwaige Fehler oder Auslassungen.
  • Zitierte Patentliteratur
    • US 62/992872 [0001]
    • US 20190236827 [0013]
    • US 16/712236 [0017]
    • US 9223578 [0017]
    • US 9164690 [0017]
    • US 20140282566 [0017]
    • US 8180998 [0018]

Claims (19)

  1. Scheduler, umfassend: einen Satz von freien Semaphoren, einen Satz von Bereitschaftssemaphoren, und Hardwareschaltungen, die mit dem Satz von freien Semaphoren und dem Satz von Bereitschaftssemaphoren wirkgekoppelt sind, die dazu konfiguriert sind, ein freies Semaphor als Reaktion auf das Reservieren einer Ressource und bei Freigabe der Ressource zu ändern, wobei der Scheduler als Reaktion auf die Werte des freien Semaphors und des Bereitschaftssemaphors eine Aufgabe startet.
  2. Scheduler nach Anspruch 1, wobei das freie Semaphor und das Bereitschaftssemaphor Zähler umfassen.
  3. Scheduler nach Anspruch 1, wobei der Scheduler die Aufgabe startet, wenn das freie Semaphor und das Bereitschaftssemaphor jeweils nicht Null sind.
  4. Scheduler nach Anspruch 1, wobei der Scheduler mit softwaredefiniertem Daten-Marshalling zusammenarbeitet, das die Ressource verwaltet.
  5. Scheduler nach Anspruch 1, wobei die Hardwareschaltung das freie Semaphor in Reaktion auf das Reservieren der Ressource für eine Aufgabe verringert und die Aufgabe das freie Semaphor beim Freigeben der reservierten Ressource erhöht.
  6. Scheduler nach Anspruch 1, wobei die Ressource verwendet wird, um Daten zwischen aufeinanderfolgenden Aufgaben in einem Graphen weiterzuleiten.
  7. Scheduler nach Anspruch 1, wobei die Semaphore die Verfügbarkeit von freiem Speicherplatz in einem Speicherpuffer oder die Menge an Cache-Druck darstellen, die durch einen Datenfluss in einem Netzwerk oder das Vorhandensein von zu verarbeitenden Arbeitsaufgaben verursacht wird.
  8. Scheduler nach Anspruch 1, wobei die Hardwareschaltung zum Zeitpunkt des Starts Ressourcen zuweist, um zu garantieren, dass die Thread-Blöcke bis zum Abschluss ausgeführt werden können.
  9. Scheduler nach Anspruch 1, wobei die Hardwareschaltung nicht mit der Anzahl von Arbeitselementen oder der Anzahl von gleichzeitig ausgeführten Thread-Gruppen von der gleichen Aufgabe/einem gleichen Knoten skaliert oder wächst.
  10. Scheduler nach Anspruch 1, wobei die Hardwareschaltung Ressourcenbeschränkungen überwacht, die einem Chip auferlegt werden, um die zum Übermitteln transienter Daten erforderliche Menge an Speicherbandbreite außerhalb des Chips zu minimieren.
  11. Scheduler nach Anspruch 1, wobei die Hardwareschaltung die Zuweisung von externem Speicher verwaltet, indem sie die Reservierung von Cache-Zeilen eines assoziativen Cache überwacht.
  12. Scheduler nach Anspruch 11, wobei der Cache so konfiguriert ist, dass er den Datenfluss zwischen Rechenstufen erfasst, ohne den Datenfluss in einen externen Speicher zu schreiben.
  13. Scheduler nach Anspruch 1, wobei der Scheduler eine Feinsynchronisation ermöglicht, indem er nicht in großen Mengen synchronisiert.
  14. In einer GPU, die Software umfasst, welche Anweisungen zum Marshallen von Daten durch eine Ressource ausführt, einen Hardware-Scheduler, der autonom Knoten eines Graphen als Reaktion auf die Überwachung der Belegung der Ressource unter Verwendung eines freien Semaphors und eines Bereitschaftssemaphors startet.
  15. Hardware-Scheduler nach Anspruch 14, ferner umfassend einen Hardware-Komparator, der die freien und Bereitschaftssemaphore mit vorbestimmten Werten vergleicht.
  16. Hardware-Scheduler nach Anspruch 15, wobei die vorbestimmten Werte Null sind.
  17. Hardware-Scheduler nach Anspruch 14, wobei die Ressource einen Cache-Speicher auf dem Chip umfasst.
  18. GPU-Scheduling-Verfahren, umfassend: (a) Subtrahieren eines freien Semaphors, um dadurch eine Ressource für eine zu startende Aufgabe zu reservieren. (b) programmgesteuertes Hinzufügen zu dem freien Semaphor und/oder zu einemBereitschaftssemaphor, wenn die Aufgabe unter Verwendung der reservierten Ressource beendet ist, und (c) Reservieren der Ressource für eine andere Aufgabe als Reaktion auf das Testen des freien Semaphors und des Bereitschaftssemaphors.
  19. GPU-Scheduling-Verfahren nach Anspruch 18, beinhaltend das Durchführen von (a)-(c) in Hardware.
DE112021000305.4T 2020-03-20 2021-03-17 Programmiermodell für ressourcenbeschränkte Planung Pending DE112021000305T5 (de)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US202062992872P 2020-03-20 2020-03-20
US62/992,872 2020-03-20
PCT/US2021/022766 WO2021188672A1 (en) 2020-03-20 2021-03-17 Programming model for resource-constrained scheduling

Publications (1)

Publication Number Publication Date
DE112021000305T5 true DE112021000305T5 (de) 2022-12-01

Family

ID=75498003

Family Applications (1)

Application Number Title Priority Date Filing Date
DE112021000305.4T Pending DE112021000305T5 (de) 2020-03-20 2021-03-17 Programmiermodell für ressourcenbeschränkte Planung

Country Status (4)

Country Link
US (1) US20210294660A1 (de)
CN (1) CN113874906A (de)
DE (1) DE112021000305T5 (de)
WO (1) WO2021188672A1 (de)

Families Citing this family (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US11481256B2 (en) * 2020-05-29 2022-10-25 Advanced Micro Devices, Inc. Task graph scheduling for workload processing
CN114610394B (zh) * 2022-03-14 2023-12-22 海飞科(南京)信息技术有限公司 指令调度的方法、处理电路和电子设备

Citations (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US8180998B1 (en) 2007-09-10 2012-05-15 Nvidia Corporation System of lanes of processing units receiving instructions via shared memory units for data-parallel or task-parallel operations
US20140282566A1 (en) 2013-03-15 2014-09-18 Nvidia Corporation System and method for hardware scheduling of indexed barriers
US9164690B2 (en) 2012-07-27 2015-10-20 Nvidia Corporation System, method, and computer program product for copying data between memory locations
US9223578B2 (en) 2009-09-25 2015-12-29 Nvidia Corporation Coalescing memory barrier operations across multiple parallel threads
US20190236827A1 (en) 2018-01-26 2019-08-01 Nvidia Corporation Techniques for representing and processing geometry within a graphics processing pipeline

Family Cites Families (2)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US4964040A (en) * 1983-01-03 1990-10-16 United States Of America As Represented By The Secretary Of The Navy Computer hardware executive
US20130198760A1 (en) * 2012-01-27 2013-08-01 Philip Alexander Cuadra Automatic dependent task launch

Patent Citations (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US8180998B1 (en) 2007-09-10 2012-05-15 Nvidia Corporation System of lanes of processing units receiving instructions via shared memory units for data-parallel or task-parallel operations
US9223578B2 (en) 2009-09-25 2015-12-29 Nvidia Corporation Coalescing memory barrier operations across multiple parallel threads
US9164690B2 (en) 2012-07-27 2015-10-20 Nvidia Corporation System, method, and computer program product for copying data between memory locations
US20140282566A1 (en) 2013-03-15 2014-09-18 Nvidia Corporation System and method for hardware scheduling of indexed barriers
US20190236827A1 (en) 2018-01-26 2019-08-01 Nvidia Corporation Techniques for representing and processing geometry within a graphics processing pipeline

Also Published As

Publication number Publication date
WO2021188672A1 (en) 2021-09-23
CN113874906A (zh) 2021-12-31
US20210294660A1 (en) 2021-09-23

Similar Documents

Publication Publication Date Title
DE102021118444A1 (de) Einrichtung und Verfahren zum Komprimieren von Strahlverfolgungsbeschleunigungsstrukturaufbaudaten
DE112012002465T5 (de) Grafikprozessor mit nicht blockierender gleichzeitiger Architektur
DE102013022712B4 (de) Virtuelle Speicherstruktur für Coprozessoren, die Speicherallokationsbegrenzungen haben
DE102013208558A1 (de) Verfahren und System zur Verarbeitung verschachtelter Stream-Events
DE112010003750T5 (de) Hardware für parallele Befehlslistenerzeugung
DE102013200991A1 (de) Automatisches abhängige-Aufgabe-Anstoßen
DE102009012766A1 (de) Ein Zugriffssperrenvorgang, um atomare Aktualisierungen zu einem geteilten Speicher zu ermöglichen
DE102020129003A1 (de) Vorrichtung und verfahren zum verwenden von alpha-werten zum verbessern einer strahlverfolgungseffizienz
DE102020101814A1 (de) Effiziente ausführung anhand von aufgabengraphen festgelegter arbeitslasten
DE102013114072A1 (de) System und Verfahren zum Hardware-Scheduling von indexierten Barrieren
DE102021120605A1 (de) Effiziente softmax-berechnung
DE102020132377A1 (de) Vorrichtung und Verfahren zur Drosselung einer Raytracing-Pipeline
DE102013020966B4 (de) Leistungseffiziente Attribut-Handhabung für Parkettierungs- und Geometrie-Schattierungseinheiten
DE112021000305T5 (de) Programmiermodell für ressourcenbeschränkte Planung
DE102013114351A1 (de) System und Verfahren für Hardware-Disponierung bedingter Barrieren und ungeduldiger Barrieren
DE102013224160A1 (de) System, Verfahren und Computer-Programm-Produkt zum Optimieren des Managements von Thread-Stapel-Speicher
DE102013201178A1 (de) Steuern von Arbeitsverteilung für Verarbeitung von Tasks
DE102020131901A1 (de) Vorrichtung und verfahren zum durchführen nicht lokaler mittelwertfilterung unter verwendung eines bewegungsschätzschaltkreises eines grafikprozessors
DE112020000865T5 (de) Speicherverwaltungssystem
DE102013020485A1 (de) Technik zur Ausführung von Speicherzugriffsoperationen über eine Textur-Hardware
DE102012210056A1 (de) Ausgeben einer kohärenten Ausgabe von mehreren Threads für printf
DE102022124599A1 (de) Vorrichtung und verfahren zur baumstrukturdatenreduzierung
DE102012220277A1 (de) Rechen-Aufgabe-Zustands-Einkapselung
DE102019117545A1 (de) Reduzierung von registerbankkonflikten für ausführungseinheiten eines multithread-prozessors
DE102020127704A1 (de) Techniken zum effizienten transferieren von daten an einem prozessor

Legal Events

Date Code Title Description
R012 Request for examination validly filed