Zum Hauptinhalt springen

Rechenressourcen und Ressourcenverwaltung

Ressourcenmodell und klassische Ressourcen

In diesem Abschnitt stellen wir einen Rahmen vor, um Rechenumgebungen zu verstehen – angefangen beim Laptop bis hin zu Supercomputern. Am Ende dieses Abschnitts kennst du die grundlegenden Bestandteile einer Rechenumgebung und weißt, wie sie miteinander zusammenhängen. Einen Überblick darüber gibt Iskandar Sitdikov im folgenden Video.

Ressourcenmodell

Jede klassische Rechenumgebung besteht aus mehreren miteinander verknüpften Ressourcen, die zusammenarbeiten, um Anwendungen effizient auszuführen. Zu den wichtigsten Ressourcen gehören typischerweise:

  • CPU (Central Processing Unit): Die CPU ist die zentrale Verarbeitungseinheit, die Programmbefehle interpretiert und ausführt. Sie übernimmt logische, arithmetische und Steuerungsoperationen und ist damit gewissermaßen das „Gehirn" des Systems.

  • CPU-Cache (L1, L2, L3): Dies ist der schnellste Speicher im System, der direkt in den CPU-Kern integriert oder sehr nah daran gebaut ist. Er speichert kleine Mengen an Daten und Befehlen, die die CPU unmittelbar benötigt. Die verschiedenen Ebenen (L1, L2, L3) stellen einen Kompromiss dar: L1 ist der kleinste und schnellste, L3 der größte und langsamste – aber immer noch um Größenordnungen schneller als RAM.

  • RAM (Random Access Memory): Flüchtiger Speicher, der großen, temporären Speicherplatz für Programmbefehle und aktiv genutzte Daten bereitstellt. Er sorgt dafür, dass die CPU während der Ausführung schnell auf benötigte Informationen zugreifen kann, ohne ständig auf langsamere Speichergeräte angewiesen zu sein.

  • Speicher (lokal und netzwerkbasiert): Speicher sichert Daten und Software auch dann, wenn das System ausgeschaltet ist, und bietet langfristige Persistenz für große Datensätze und Anwendungen. In Hochleistungsrechenzentren müssen Speicherlösungen riesige Mengen wissenschaftlicher oder analytischer Daten schnell und zuverlässig verarbeiten. Lokaler Speicher umfasst Solid-State-Drives (SSDs) und Festplatten (HDDs); SSDs werden wegen ihrer geringeren Latenz und höheren Übertragungsrate bevorzugt. Für die Verarbeitung großer Datenmengen ermöglichen parallele Dateisysteme, gemeinsam genutzter Netzwerkspeicher und objektbasierte Systeme schnellen Zugriff über viele Rechenknoten hinweg, während Cloud- und Archivspeicher die langfristige Aufbewahrung und Skalierbarkeit unterstützen.

  • GPU (Graphics Processing Unit): Obwohl ursprünglich für die Grafikdarstellung entwickelt, sind moderne GPUs leistungsstarke Parallelprozessoren. Sie werden häufig für Aufgaben eingesetzt, die viele gleichzeitige Berechnungen erfordern, wie Deep Learning, Physiksimulationen und Big-Data-Analysen. Wichtig ist dabei: GPUs ersetzen CPUs nicht – CPUs steuern die übergeordnete Programmlogik, während GPUs hochparallele Schritte beschleunigen.

  • Verbindungen/Busse: Das sind Kommunikationswege, die CPU, Speicher, Datenspeicher und Peripheriegeräte miteinander verbinden. Busse ermöglichen den Datentransfer und die Koordination zwischen Systemkomponenten und sorgen für eine reibungslose Kommunikation innerhalb der Rechenumgebung. In HPC-Systemen sind Komponenten wie CPUs, GPUs und Speichergeräte durch Hochgeschwindigkeits-Interconnects verbunden, die einen schnellen Datenaustausch ermöglichen. GPUs sind üblicherweise über PCIe mit dem System verbunden, eine Standardschnittstelle mit mehreren Datenleitungen für effiziente Kommunikation. Für höhere Leistung bietet NVLink eine direkte, hochbandbreitige Verbindung zwischen GPUs oder zwischen GPUs und CPUs, was Latenz reduziert und parallele Workloads beschleunigt.

  • Dateisystem: Das Dateisystem organisiert Daten auf Speichergeräten. Es schafft eine Struktur zum Speichern, Abrufen und Verwalten von Dateien und ermöglicht es Programmen und Nutzenden, auf Informationen konsistent und logisch geordnet zuzugreifen.

Jede Ressourcentyp hat seine eigenen leistungsbezogenen Maßeinheiten. CPUs werden beispielsweise typischerweise nach „Kernen" und „Taktfrequenz" bewertet. Beim Kauf eines Laptops sind diese Angaben in der Regel in den technischen Daten enthalten. Ähnliches gilt für Rechenknoten in einem Rechenzentrum, wo jeder Knoten einer bestimmten Anzahl von Kernen zugeordnet ist. Rechenumgebungen, die mehrere Ressourcentypen umfassen (CPUs, GPUs, sogar QPUs), werden als heterogene Rechenumgebungen bezeichnet. Diese Setups verarbeiten unterschiedliche Workloads effizienter, indem sie die Stärken jedes Prozessortyps nutzen – zum Beispiel CPUs für allgemeine Aufgaben und GPUs für Parallelverarbeitung. Im Kontext des Ressourcenmanagements und der Planung – insbesondere für heterogene Rechenumgebungen – können zusätzliche Maßeinheiten erforderlich sein.

Für Arbeitsspeicher ist die Maßeinheit Mega-/Giga-/Terabyte.

Bei Grafikkarten und anderen Beschleunigern hängt die Maßeinheit vom Kontext ab. Während ihre eigentliche Rechenleistung durch detaillierte Kennzahlen beschrieben wird – Anzahl der Verarbeitungskerne, Speichergröße und Speicherbandbreite –, werden GPUs und ähnliche Beschleuniger in übergeordneten Diskussionen über Clusterressourcen oder Job-Scheduling auf Geräteebene quantifiziert, also durch die Anzahl der zugewiesenen ganzen Geräte (z. B. drei GPUs).

Netzwerk/Konnektivität/Busse sind entscheidende Aspekte jeder Recheninfrastruktur, da sie bestimmen, wie schnell Daten zwischen Rechenkomponenten übertragen werden. Von der CPU zum CPU-Cache, zum RAM, zu PCI-Karten bis hin zu netzwerkverbundenen Geräten – alles ist Kommunikation, und ein präzises mentales Modell davon ist unerlässlich, um hochoptimierte Algorithmen für HPC zu entwickeln.

Ein Bild, das zeigt, dass jeder Rechenknoten viele verschiedene Ressourcentypen enthalten kann.

Skalierung klassischer Ressourcen

High-Performance Computing (HPC) beinhaltet die Skalierung dieser klassischen Ressourcen, um schnellere Verarbeitungszeiten zu erreichen oder die gleichzeitig verarbeitbaren Datenmengen zu erhöhen (z. B. um den Lösungsraum zu vergrößern, der durchsucht werden kann). Dies kann erreicht werden durch:

  • Vertikale Skalierung: Erhöhung der Leistung einzelner Ressourcen, beispielsweise durch eine leistungsstärkere CPU oder zusätzlichen Arbeitsspeicher innerhalb eines physischen Knotens – wobei ein Knoten eine Einheit eines Rechenclusters ist, die mehrere Rechenressourcen zusammenfasst.

  • Horizontale Skalierung: Hinzufügen weiterer Ressourcen, etwa mehrerer CPUs oder GPUs, die gemeinsam auf einem einzelnen Knoten oder – häufiger – auf mehreren Knoten arbeiten, um verteiltes Rechnen zu ermöglichen.

Ein Bild, das vertikale Skalierung durch das Hinzufügen von Ressourcen wie Arbeitsspeicher innerhalb eines einzelnen Knotens zeigt, sowie horizontale Skalierung durch die Erhöhung der Anzahl verbundener Knoten mit unterschiedlichen Ressourcentypen.

Einige der Skalierungskonzepte aus diesem Abschnitt lassen sich auf den nächsten Abschnitt über Quantenrechenressourcen übertragen. Andere Aspekte von Quantenressourcen werden auf neue Arten quantifiziert.

Verständnisfragen

Leite anhand der obigen Beschreibungen einige Vor- und Nachteile der verschiedenen Skalierungsansätze ab: vertikale und horizontale Skalierung?

Antwort:

Es gibt möglicherweise viele richtige Antworten. Vertikale Skalierung ist oft einfacher, besonders wenn du vorhersehbare Workloads mit einem festen Ressourcenbedarf hast. Sie kann jedoch teurer in der Aufrüstung sein, da die grundlegende Recheneinheit nicht so leicht aufgeteilt werden kann wie bei der horizontalen Skalierung. Horizontale Skalierung ist komplexer zu verwalten, und manchmal entstehen Schwierigkeiten oder Latenzen durch die Verbindungen zwischen Knoten. Dafür passt sie sich viel besser an variierende Ressourcenanforderungen an und ist modular, wenn Upgrades nötig sind.

Neuer Ressourcentyp: QPU (Quantum Processing Unit)

In diesem Abschnitt stellen wir einen neuen Ressourcentyp vor – eine Quantenressource – und erkunden seine Definition, Maßeinheiten und Anbindung an klassische Infrastruktur.

Definition einer QPU

  • Quantum Processing Unit (QPU): Eine QPU umfasst die gesamte Hardware, die dafür verantwortlich ist, einen ausführbaren Quanten-Befehlssatz oder einen Quantum Circuit entgegenzunehmen und ein genaues Ergebnis zurückzugeben.

Das bedeutet, dass die QPU einen oder mehrere Quantenchips (z. B. Heron), die verschiedenen zusätzlichen Komponenten im Verdünnungskühlschrank wie Quantenverstärker, die Steuerelektronik und die klassische Rechenkapazität umfasst, die für Aufgaben wie das Halten von Befehlen und Wellenformen im Speicher, das Akkumulieren von Ergebnissen und die zukünftige Fehlerkorrektur-Dekodierung benötigt wird. Obwohl ein Verdünnungskühlschrank für diese Aufgaben erforderlich ist, schließen wir ihn aus dieser Definition aus, um den Fall mehrerer QPUs in demselben Kühlschrank zu ermöglichen.

  • Quantencomputer: Ein Quantencomputer besteht aus der QPU plus der klassischen Rechenkapazität, die die Laufzeitumgebung hostet.

  • Laufzeitumgebung: Die Kombination aus Hardware und Software, die es ermöglicht, ein Programm auszuführen.

Schichten in Quantum Circuits

Sowohl im klassischen als auch im Quantencomputing können Prozesse sequenziell oder parallel ausgeführt werden. Da Qubits einen reichhaltigeren Zustandsraum haben als klassische Bits, ist es manchmal sinnvoll, mehrere Einzelqubit-Gates nacheinander auf einem Qubit auszuführen (z. B. ein R_x-Gate gefolgt von einem R_z-Gate). Da die Verschränkung zwischen Qubits für das Quantencomputing entscheidend ist, enthält ein Quantum Circuit häufig eine Menge von Verschränkungs-Gates, die über viele Qubits hinweg wirken. Diese und andere Faktoren machen es üblich, Prozesse zu identifizieren, die auf der Ebene einzelner Gate-Operationen in einem Quantum Circuit parallel ausgeführt werden können. Im klassischen Computing ist Parallelismus auf Bit-Ebene ebenfalls möglich, wird aber auf Gate-Ebene weniger häufig betrachtet; üblicher ist es, parallele und sequenzielle Prozesse auf einer größeren Skala zu beschreiben.

Im Quantencomputing bezeichnet man eine „Schicht" von Gates, die alle gleichzeitig ausgeführt werden können. In vielen Anwendungen ist es nützlich, zunächst eine Menge von Rotationen auf allen Qubits und dann Verschränkungs-Gates zwischen Qubit-Paaren auszuführen. In diesen Kontexten spricht man von einer „Rotationsschicht" (einer Schicht mit Gates wie R_x, R_y und/oder R_z) und einer „Verschränkungsschicht" (z. B. mit CNOT-Gates). Die Anzahl der Schichten in einem Circuit ist die „Circuit-Tiefe", ein wichtiges Maß, da größere Tiefe mehr Schichten kumulierenden Rauschens und Fehler bedeutet.

Gate-Schichten lassen sich visuell schwer erkennen, wenn sie nicht durch Barrieren ausgerichtet sind. In Qiskit dient eine Barriere als Anweisung in Quantum Circuits, die sowohl als visueller Trenner als auch als Compilierungsbeschränkung wirkt. Beim Zeichnen und Ausführen des Circuits werden keine Gates über die Barriere hinaus verschoben. Das ist in Kontexten wie dem Dynamical Decoupling wichtig, bei dem absichtlich Gates implementiert werden, die sich zur Identität vereinfachen, um bestimmte Fehlertypen zu unterdrücken. Mehr zum Dynamical Decoupling findest du in diesem Leitfaden. Für die visuelle Wirkung von Barrieren vergleiche diese beiden Bilder desselben Circuits – das erste ohne Barrieren, das zweite mit Barrieren zur erzwungenen Ausrichtung der Schichten.

Vier-Qubit-Quantum-Circuit ohne Barrieren zur Ausrichtung der Schichten; Gates erscheinen etwas ungeordnet ausgerichtet.

Vier-Qubit-Quantum-Circuit mit Barrieren, die die Ausrichtung der Schichten erzwingen. Das Zählen der Schichten ist jetzt viel einfacher.

Das sind dieselben Circuits mit derselben Anzahl von Schichten. Im zweiten macht die Ausrichtung es jedoch leicht zu erkennen, dass der Circuit folgendes enthält:

  • Zwei Rotationsschichten: eine um die Y-Achse um π/5\pi/5, eine um die Z-Achse um π/4\pi/4.
  • Drei Verschränkungsschichten. Beachte, dass man jedes CNOT als eigene „Schicht" zählen kann, da die CNOTs nicht neu angeordnet werden können, ohne die logische Operation zu ändern.
  • Zwei weitere Rotationsschichten: eine um die Y-Achse um π/3\pi/3, eine um die Z-Achse um π/2\pi/2.
  • Zwei weitere Verschränkungsschichten. Diesmal wurde die erste Schicht etwas stärker parallelisiert als in der ersten Gruppe von Verschränkungsschichten.

Die Tiefe jedes Circuits beträgt 9.

Maßeinheiten

Im Quantencomputing werden die Fähigkeiten eines Quantensystems typischerweise anhand von drei wesentlichen Leistungskennzahlen bewertet: Skalierung, Qualität und Geschwindigkeit. Diese Kennzahlen beschreiben nicht nur das rechnerische Potenzial eines Quantengeräts, sondern geben auch Aufschluss darüber, wie Ressourcen in der Praxis verwaltet und eingeplant werden.

  • Skalierung bezieht sich auf die Anzahl der Quantenbits (Qubits) im System und gibt an, wie viel Quanteninformation das Gerät halten kann. Im Ressourcenmanagement beeinflusst dies direkt die Circuit-Breite – die Anzahl der Qubits, die für eine bestimmte Quantenaufgabe benötigt werden. Eine Quanteneinheit muss über ausreichend Qubits verfügen, um die zugewiesene Aufgabe zu unterstützen.

  • Qualität beschreibt, wie genau Quantenoperationen ausgeführt werden. Sie wird oft durch die Layer-Fidelity quantifiziert, die die Genauigkeit bei der Ausführung einer vollständigen Schicht von Quantum Gates über alle Qubits hinweg misst. Aus Planungsperspektive ermöglicht höhere Fidelity die zuverlässige Ausführung tieferer Circuits, was den Bedarf an Fehlerminderung oder Aufgabenzerlegung beeinflusst.

  • Geschwindigkeit wird durch CLOPS (Circuit Layer Operations Per Second) gemessen und gibt an, wie viele Schichten von Quantenoperationen das System pro Sekunde ausführen kann. Dies beeinflusst Durchsatz und Latenz bei der Aufgabenausführung und hilft zu bestimmen, wie schnell eine Quanteneinheit eine bestimmte Arbeitslast abschließen kann. Diese Geschwindigkeit ist bei einem Quantencomputer besonders wichtig, da Qubits stärker von Rauschen und Fehlern betroffen sind als ihre klassischen Pendants. Der Zeitraum, über den sie ihre Quanteninformation auf nützliche Weise aufrechterhalten können, wird durch die Kohärenzzeit beschrieben und beträgt für Heron-r3-Prozessoren typischerweise etwa 200–300 μs\mu\text{s}.

Unterschiede zwischen Quanten- und klassischen Kennzahlen

Du kannst CLOPS als grobes Quantenäquivalent zu FLOPS betrachten, aber mit einigen wesentlichen Unterschieden. CLOPS misst die Geschwindigkeit, mit der ein Quantenprozessor Quantum Circuits ausführen kann – speziell Schichten von Operationen innerhalb der Circuits, einschließlich sowohl quantenmechanischer als auch notwendiger klassischer Berechnungen beim Ausführen von Circuits. Es wurde von IBM Quantum als ganzheitliches Maß für die Ausführungsgeschwindigkeit eines Quantencomputers entwickelt und umfasst die Quantenausführungszeit sowie die klassische Echtzeitverarbeitung für Circuit-Aktualisierungen – anders als FLOPS, das rein die Gleitkomma-Arithmetikkapazität klassischer Prozessoren misst.

CLOPS liefert eine messbare Leistungskennzahl, die auf vorhandener Hardware benchmarkt werden kann. IBM Quantum hat CLOPS verwendet, um verschiedene Quantenprozessoren zu benchmarken; die Werte sind auf der Seite Compute resources auf IBM Quantum Platform zu finden. CLOPS-Werte hängen von Hardware-Fähigkeiten, Gate-Geschwindigkeiten, klassischer Verarbeitungsgeschwindigkeit und deren Zusammenspiel ab.

Die Qubit-Anzahl ist für eine gegebene QPU eine feste Zahl. CLOPS und Qualität hängen von regelmäßiger Kalibrierung und Wartung ab und können im Laufe der Zeit leicht variieren, selbst für eine einzelne QPU.

Zusammen leiten diese Kennzahlen die Zuweisung und Planung von Quantensystemen. In vielen Fällen wird das gesamte Quantensystem als eine einzige Einheit behandelt. Wenn eine Aufgabe jedoch die Kapazität einer Einheit übersteigt – sei es in Bezug auf Qubit-Anzahl, Circuit-Tiefe oder Ausführungsgeschwindigkeit – können Techniken wie Circuit Cutting/Knitting eingesetzt werden. Circuit Cutting bezeichnet den Prozess, bei dem große Quantenaufgaben in kleinere, handhabbare Teilaufgaben aufgeteilt werden, die auf mehrere Quantenchips verteilt werden können, um skalierbare Quantenberechnungen trotz Hardware-Einschränkungen zu ermöglichen. Circuit Knitting bezeichnet den nachgelagerten Prozess – den klassischen Nachverarbeitungsschritt, der die Ergebnisse der kleineren Teilcircuits wieder zusammenfügt.

Quantencomputer haben keinen traditionellen Speicher im Sinne von persistentem, adressierbarem Speicher wie RAM oder GPU-Speicher. Klassische Rechenressourcen haben diskrete Bits, die im Speicher abgelegt sind, sodass Daten während der Berechnung gespeichert, abgerufen und wiederverwendet werden können. Quantenressourcen verwenden Qubits, die Speicher nicht im klassischen Sinne speichern. Stattdessen existieren Qubits in Quantenzuständen, die Superpositionen von 0 und 1 gleichzeitig darstellen, was exponentielle Parallelität im Zustandsraum ermöglicht. Qubit-Zustände sind jedoch fragil und können ohne Kollaps des Quantenzustands weder geklont noch deterministisch in Zwischenschritten ausgelesen werden, sodass persistentes speicherähnliches Verhalten während der Berechnung nicht existiert. Qubits müssen während der gesamten Ausführung in einem kohärenten Zustand gehalten werden, und der „Speicher" ist im Wesentlichen der Quantenzustand selbst. Klassischer Speicher kann nur neben einem Quantenprozessor verwendet werden, nicht als interner Quantenspeicher. Das hat erhebliche Auswirkungen: Klassische Rechenressourcen können Zwischenergebnisse frei wiederverwenden und speichern; Quantenressourcen können das nicht, ohne Messungen durchzuführen, die die Berechnung stören.

Anbindung an klassische Infrastruktur

QPUs können über Netzwerke und verschiedene Application Programming Interfaces (APIs) mit klassischer Infrastruktur verbunden werden, die es Softwareentwicklern ermöglichen, programmatisch mit QPUs zu interagieren. Diese APIs sind in der Regel hinter Software Development Kits (SDKs) und Bibliotheken (wie Qiskit) verborgen und werden Berechnungswissenschaftlern in Form von Programmierabstraktionen (wie den Qiskit Primitives, über die wir in Kapitel 3: Programmiermodelle sprechen werden) zugänglich gemacht.

Es lohnt sich, zwischen enger und loser Integration von Quanten- und klassischen Ressourcen zu unterscheiden. Derzeit befinden sich QPUs nicht auf demselben Knoten wie klassische Rechenressourcen. Tatsächlich sind QPUs aktuell nicht über PCIe, sondern über das Netzwerk verbunden. Das könnte sich in Zukunft ändern, aber es gibt technische Herausforderungen, die mit den unterschiedlichen optimalen Umgebungsbedingungen für QPUs und klassische Rechenressourcen zusammenhängen.

Skalierung von Quantenressourcen

Die Skalierung von Quantenressourcen lässt sich ebenfalls in vertikale und horizontale Skalierung einteilen.

  • Vertikale Skalierung wäre die Erhöhung der Qubit-Anzahl pro Chip oder die Verbesserung der Fidelity von Geräten.
  • Horizontale Skalierung wäre die Verbindung von Chips mit Kopplern oder über klassische Interconnects.

Ein Bild, das vertikale Skalierung von Quantenressourcen als mehr Qubits auf einem Chip zeigt, und horizontale Skalierung als die Verbindung vieler Chips mit Kopplern.

Verständnisfragen

Was sind die Quanten-Entsprechungen zu (a) klassischen Informationsbits und (b) Prozessorgeschwindigkeit?

Antwort:

(a) Quantenbits oder Qubits – Informationseinheiten, die im Gegensatz zu ihren klassischen Pendants (die nur den Zustand 0 oder 1 annehmen können) gleichzeitig in einer Superposition von 0 und 1 sein können.

(b) Circuit Layer Operations per Second oder CLOPS – die Anzahl sequenzieller Operationen, die die QPU pro Sekunde ausführen kann, einschließlich einiger Schnittstellen mit klassischen Rechenressourcen, wie beim Laden von Parametern aus dem Circuit.

Ressourcenverwaltung

Sowohl HPC- als auch Quantenressourcen sind wertvoll und komplex; sie müssen sorgfältig verwaltet werden. In diesem Abschnitt erklären wir, wie Ressourcen für Benutzerprogramme verwaltet werden. Ressourcenverwaltung in Recheninfrastrukturen bezieht sich auf den Prozess der (1) Planung, (2) Zuweisung und (3) Steuerung/Verwaltung des Einsatzes von Rechenressourcen wie CPUs, Speicher, Datenspeicher und Netzwerkbandbreite, um eine effiziente und effektive Ressourcennutzung zu gewährleisten.

Planung – Ressourcenschätzung

Jedes Programm verbraucht Ressourcen, und die Schätzung des benötigten Ressourcenbedarfs ist entscheidend für ein effizientes Ressourcenmanagement. Dazu gehört die Schätzung des CPU-, Speicher- und sonstigen Ressourcenbedarfs zur Ausführung eines Programms. Dasselbe gilt für Quantenressourcen. Allerdings existieren Quantenressourcen auf einer völlig anderen Größenordnung. IBM Quantum® Heron-r3-Quantenprozessoren haben 156 Qubits, verglichen mit den vielen Milliarden klassischer Bits auf einem gewöhnlichen Laptop. Zeit und Kosten sind ebenfalls zu berücksichtigen. Derzeit bietet IBM Quantum einen kostenlosen Tarif an, den Open Plan, der es Nutzenden ermöglicht, Quantencomputing mit 10 Minuten QPU-Zeit pro Monat zu erkunden. Einige Forschungsorganisationen benötigen so viel QPU-Zeit, dass sie einen dedizierten IBM-Quantencomputer vor Ort haben.

Ein Schritt in der Ressourcenschätzung, der einzigartig für das Quantencomputing ist, ist die Circuit-Tiefe. Wie bereits erwähnt, bringt jedes Quantum Gate und jede Verzögerungszeit zwischen Operationen Rauschen und eine gewisse Fehlerwahrscheinlichkeit mit sich. Je tiefer der Quantum Circuit, desto größer das Rauschen. Es gibt dabei zwei Feinheiten: Zwei-Qubit-Gates haben viel höhere Fehlerraten als Einzelqubit-Gates, daher kann man die Einzelqubit-Tiefe oft vernachlässigen. Außerdem sind nicht alle Qubits auf einem Quantenchip direkt miteinander verbunden. Manchmal müssen Informationen von Qubit zu Qubit getauscht werden, um die erforderlichen Verschränkungen durchführen zu können, und dieser Tauschprozess selbst erfordert Zwei-Qubit-Gates. Dieser Tausch wird in einem Prozess namens „Transpilation" durchgeführt, einem komplexen Prozess, der auch anderen Zwecken dient; darauf wird in der nächsten Lektion ausführlicher eingegangen. Die relevante limitierende Größe ist daher die transpilierte Zwei-Qubit-Tiefe. Die genaue maximale Tiefe, bei der hochgenaue Ergebnisse erzielt werden können, hängt vom Circuit ab. Mit modernen Fehlerminderungstechniken lassen sich jedoch hochgenaue Ergebnisse bei transpilierten Zwei-Qubit-Tiefen von 80 oder mehr erzielen.

Zuweisung – Scheduling

Scheduling ist der Prozess der Zuweisung von Ressourcen zu Programmen und der Verwaltung ihrer Ausführung. Dies umfasst:

  • Job-Einreichung: Der Prozess, bei dem ein Benutzer eine Anfrage (Job) an das HPC-System sendet und dabei angibt, welche Rechenarbeit und welche Ressourcen für die Ausführung benötigt werden.
  • Ressourcenzuweisung: Die Zuweisung verfügbarer HPC-Systemressourcen (wie Knoten, CPUs, Speicher) an einen eingereichten Job basierend auf seinen Anforderungen.
  • Job-Ausführung: Das tatsächliche Ausführen der vom Job definierten Rechenaufgaben auf den zugewiesenen HPC-Ressourcen.

Für Quantencomputer gibt es Entsprechungen all dieser Prozesse.

  • Jobs werden vom Benutzer über Qiskit Runtime eingereicht, typischerweise unter Verwendung eines Qiskit-Runtime-Primitives wie Sampler, Estimator oder anderen.
  • Der Benutzer wählt aus einer Liste von Backends aus, auf die er Zugriff hat. Die vollständige Liste der verfügbaren Backends ist auf der Seite Compute resources auf IBM Quantum Platform zu finden. In der Regel wird einfach der am wenigsten ausgelastete Quantencomputer verwendet. Es gibt jedoch Fälle, in denen es wichtig sein kann, einen bestimmten zu verwenden, z. B. aufgrund von Gerät-Layout-Überlegungen, der Reproduktion früherer Berechnungen usw.
  • Die Ausführung von Quanten-Jobs ähnelt dem HPC-Fall. Obwohl einige Unterschiede bereits dargelegt wurden, lohnt es sich, einige hier zu wiederholen. QPUs befinden sich derzeit im Allgemeinen nicht auf demselben Knoten wie klassische Rechenressourcen, sondern sind über ein Netzwerk verbunden. Das kann Scheduling-Implikationen haben. Außerdem können Quantencomputer erhebliche Warteschlangenzeiten haben, die variieren und eine genaue Zeitsteuerung erschweren. Diese Situation kann für dedizierte Systeme anders sein; das hängt von der internen Verwaltung des Quantencomputers ab.

Steuerung/Verwaltung – Workload-Management

Workload-Management, auch als Orchestrierung bezeichnet, ist der Prozess der Verwaltung mehrerer Programme und ihrer Ressourcenanforderungen. Dies umfasst:

  • Ressourcenbereitstellung: Der Prozess der Vorbereitung und Bereitstellung von HPC-Ressourcen für die Nutzung durch Jobs, einschließlich Hardware- und Software-Einrichtung. Wie wir später sehen werden, sind QPUs Rechenressourcen, die ähnlich wie klassische HPC-Ressourcen bereitgestellt werden können, mit den Einschränkungen aus dem vorherigen Abschnitt.
  • Job-Scheduling: Die Aktivität der Scheduling-Software, die entscheidet, welche Jobs wann und auf welchen Ressourcen ausgeführt werden, und dabei Prioritäten und Warteschlangen verwaltet, um das HPC-System effizient zu nutzen. Obwohl diese übergeordnete Aussage für Quantenressourcen gilt, kann die Kontrolle über das Timing weniger präzise sein als bei anderen Ressourcen.

Ein Bild, das Workloads (als Kästchen dargestellt) zeigt, die organisiert und angeordnet werden, um optimal in ein zweidimensionales Raster zu passen, mit einer Achse für die Zeit und der anderen für Ressourcen. Beispiel:

Betrachten wir eine bekannte Aufgabe als Kontext für das Verständnis des Ressourcenmanagements: die Suche nach den Primfaktoren großer Zahlen. Nehmen wir weiter an, dass der verwendete Algorithmus auf dem brutalen Überprüfen jedes potenziellen Teilers beruht. Obwohl dies oft nicht die effizienteste Methode ist, lässt sich leicht verstehen, wie die Arbeitslast verwaltet werden könnte.

Planung – Ressourcenschätzung

  • Schätze, wie viel CPU-Zeit und Speicher die Primfaktorzerlegung benötigen könnte.
  • Plane die Parallelisierung deiner Aufgabe – wie viele CPUs/Kerne wirst du verwenden?

Zuweisung – Scheduling

  • Bei der Job-Einreichung weist der Scheduler der Primfaktorzerlegungsaufgabe CPU-Kerne und Speicher zu. Beispielsweise könnte er alle potenziellen Teiler, die mit den Ziffern 1, 3, 7, 9 enden, jeweils einem von vier Kernen zuweisen.
  • Job-Ausführung: Der Primfaktorzerlegungsalgorithmus läuft und führt Divisionen oder andere Faktorisierungsschritte auf den zugewiesenen Ressourcen durch, bis die Aufgabe abgeschlossen ist.

Steuerung/Verwaltung – Workload-Management

  • Das System orchestriert die Reihenfolge und das Timing der Primfaktorzerlegungsjobs, um den Durchsatz zu optimieren.
  • Der einfachste vorstellbare Fall ist, dass einer der Kerne den gesuchten Primfaktor findet. Das sollte die Berechnung auf anderen Kernen stoppen, damit diese für die nächste Aufgabe genutzt werden können.

High-Performance-Computing-Umgebungen verwenden spezielle Software, um diese Schritte durchzuführen und Ressourcen zu verwalten. Im nächsten Abschnitt lernen wir ein weit verbreitetes Ressourcenverwaltungssystem kennen: Slurm.

Beispiel mit Quantenressourcen:

Ein Workflow, der Gegenstand anderer Lektionen in diesem Kurs sein wird, ist die Bestimmung chemischer Grundzustände und Energien mittels Sample-Based Quantum Diagonalization (SQD). Dies wird ausführlicher in Lektion 4 behandelt; du kannst auch diesen Kurs über SQD und verwandte Methoden auf IBM Quantum Learning besuchen. Alles, was wir für diese Diskussion wissen müssen, ist, dass der Workflow folgendes umfasst:

  • Vorbereitung eines Quantum Circuits
  • Messung des Quantum Circuits
  • Verwendung der Messergebnisse, um das Problem in einen nützlichen Unterraum zu projizieren
  • Diagonalisierung einer kleineren, projizierten Matrix mit klassischen Rechenressourcen
  • Iteration, entweder zur Gewährleistung der Selbstkonsistenz durch Überlegungen wie die Ladungserhaltung, und mögliche Iterationen des Quantum Circuits, wenn er variationale Parameter hat.

Planung – Ressourcenschätzung

  • Ordne die elektronischen Orbitale Qubits zu, um die Anzahl der benötigten Qubits festzustellen.
  • Kombiniere den abgebildeten Hamiltonoperator des Systems und den (möglicherweise variationalen) Zustand in einem Quantum Circuit und überprüfe die transpilierte Zwei-Qubit-Tiefe. Stelle sicher, dass sie sinnvoll ist.
  • Schätze die Größe des Unterraums, in den du projizieren wirst; schätze daraus, wie viel CPU-Zeit und Speicher die Diagonalisierung benötigen könnte.
  • Plane die Parallelisierung deiner Aufgabe – wie viele CPUs/Kerne wirst du verwenden?

Zuweisung – Scheduling

  • Der Benutzer wählt die QPU aus; der Transpilierungsprozess ordnet die Qubits in deinem abstrakten Quantum Circuit automatisch physischen Qubits auf der QPU zu. Das ist wichtig, da der abstrakte Circuit möglicherweise eine direkte Konnektivität annimmt, die auf dem Chip nicht vorhanden ist, unter anderem.
  • Bei der Job-Einreichung über Qiskit Runtime tritt der Job in die Warteschlange für die ausgewählte QPU ein. Der Benutzer hat keine Kontrolle über die Warteschlangenzeit, obwohl dies bei dedizierten Systemen anders sein kann.
  • Klassische Rechenressourcen warten auf die Quantenergebnisse.
  • Ein Diagonalisierungsjob wird an HPC-Ressourcen eingereicht; bei der Job-Einreichung weist der Scheduler der Diagonalisierungsaufgabe CPU-Kerne und Speicher zu.
  • Job-Ausführung: Der Diagonalisierungsalgorithmus läuft und diagonalisiert die kleinere projizierte Matrix, bis die Aufgabe abgeschlossen ist.

Steuerung/Verwaltung – Workload-Management

  • Das System orchestriert die Reihenfolge und das Timing der Quanten- und klassischen Schritte durchgehend. Wenn z. B. die projizierte Matrix diagonalisiert und eine Grundzustandsenergie erhalten wurde, kann der Workflow abhängig von Konvergenzkriterien zu einem neuen Quantum Circuit (mit einem neuen variationalen Parameter) zurückschleifen.
  • Wenn Konvergenzkriterien durch die Grundzustandsenergie erfüllt sind, stoppt die Berechnung auf allen Kernen.

High-Performance-Computing-Umgebungen verwenden spezielle Software, um diese Schritte durchzuführen und Ressourcen zu verwalten. Im nächsten Abschnitt lernen wir ein weit verbreitetes Ressourcenverwaltungssystem kennen: Slurm. Es ist wichtig zu beachten, dass Slurm keine Werkzeuge für alle oben beschriebenen Schritte bereitstellt. Slurm bietet keine Unterstützung für die Planung von Jobs, noch für detailliertes Workload-Management wie die Kommunikation zwischen Workload-Komponenten. Das passt gut zum aktuellen Stand des Quantencomputings in HPC, da QPUs typischerweise über das Netzwerk zugänglich sind.

Verständnisfragen

Angenommen, du versuchst, eine unsortierte Datenbank zu durchsuchen, um ein Element zu finden, das wir „Ziel" nennen. Ordne jede der folgenden Aktionen der entsprechenden Phase des Ressourcenmanagements zu: (a) Schätzung der Größe der Datenbank und der Zeit, die zur Überprüfung jedes Elements benötigt wird (b) Sicherstellen, dass das Finden des Ziels auf einer GPU den Prozess auf anderen GPUs stoppt, um sie für das nächste Problem freizugeben. (c) Aufteilung des Suchraums in Regionen für jede deiner (sagen wir 10) GPUs

Antwort:

(a) Planung (b) Steuerung/Verwaltung (c) Zuweisung/Scheduling,

Software: Slurm

In diesem Abschnitt wenden wir die in diesem Kapitel gelernten Konzepte an, um das beliebte Ressourcenverwaltungssystem Slurm in der Praxis zu nutzen.

Einführung in Slurm

Slurm ist ein Open-Source-Ressourcenverwaltungssystem, das in High-Performance-Computing-Umgebungen weit verbreitet ist. Es bietet einen umfassenden Satz von Werkzeugen zur Verwaltung von Ressourcen, zum Scheduling von Jobs und zur Überwachung der Systemleistung.

Wir behandeln die Grundlagen der Verwendung von Slurm, einschließlich:

  • Job-Einreichung
  • Ressourcenzuweisung
  • Job-Überwachung

Da es wirklich schwierig ist, jedem Studierenden dieses Kurses HPC-Ressourcen bereitzustellen, mogeln wir ein bisschen und stellen dir ein Repository mit Docker-Images zur Verfügung, die einen echten HPC-Cluster mit Slurm im kleinen Maßstab imitieren. Das hilft uns, gelernte Konzepte in sicheren, reproduzierbaren Umgebungen zu üben.

Beachte, dass derzeit alle Quanten- und klassischen Ressourcen für die gesamte Dauer des Experiments zugewiesen werden. Es gibt derzeit keine verschachtelte Zuweisung gemischter Ressourcen. Ein letzter Vorbehalt ist, dass selbst nach dem Start des Jobs das Quantensystem nicht direkt so gesteuert wird, wie es ein erfahrener HPC-Benutzer erwarten würde. Der Job wird auf einem beliebigen x86-Knoten gestartet, der den Qiskit-Runtime-Dienst ausführt, und dieser Runtime-Dienst verbindet sich mit einem anderen Scheduler, über den der Benutzer keine direkte Kontrolle hat. Dieser Workflow und verwandte Probleme sind möglicherweise HPC-Benutzern bekannt, die frühzeitig exklusiven Zugang zu GPU-Knoten gesucht haben (der ursprüngliche Verwendungszweck von gres).

Installationsanleitung und Einrichtungsübersicht

Um das Kombinieren von Quanten- und HPC-Ressourcen zu üben, benötigst du entweder Zugang zu einer echten HPC-Umgebung oder du musst eine HPC-Umgebung auf deinem lokalen Rechner simulieren. Eine Installationsanleitung für die lokale Einrichtung mit Docker findest du in diesem Repository. Die Anleitung verweist auf Hilfe zur Einrichtung eines IBM Cloud®-Kontos und zur Installation des SPANK-Plugins für QRMI. Ebenfalls in diesem Repository befinden sich mehrere Python-Dateien zum Testen deiner Umgebung.

Nach Abschluss der Installation prüfen wir mit dem folgenden Befehl die Rechenressourcen von Slurm in deinem Terminal. Wenn die Installation erfolgreich war, solltest du insgesamt drei virtuelle Knoten bestätigen können.

$ sinfo

PARTITION AVAIL TIMELIMIT NODES STATE NODELIST
normal up 5-00:00:00 2 idle c[1-2]
quantum* up infinite 1 idle q1
$ scontrol show node

NodeNAME=q1 Arch=x86_64 CoresPerSocket=1
CPUAlloc=0 CPUTot=1 CPULoad=0.34
AvailableFeatures=(null)
ActiveFeatures=(null)
Gres=qpu:1
NodeAddr=q1 NodeHostName=q1 Version=21.08.6
...

Wir haben zwei Partitionen oder Knotengruppen: normal und quantum. Die normale Partition besteht aus Knoten, die nur Zugang zu klassischen Ressourcen haben. Die Quantum-Partition hat Zugang zu Quantenressourcen. Du kannst die Details jedes Knotens durch Ausführen von scontrol show nodes sehen.

Führe ein einfaches „Hello World"-Beispiel in Slurm aus

Lass uns zunächst ein einfaches klassisches hello world-Beispiel mit Slurm ausführen. Wir verwenden Python für die Beispiele. Erstellen wir hello_world.py, das selbsterklärend ist.

$ vim hello_world.py

import time
time.sleep(10)
print("Hello, World!")
~

Jetzt müssen wir dem Ressourcenmanager mitteilen, welche Ressourcen wir zur Ausführung dieses Programms benötigen. Slurm bietet eine Möglichkeit, alle Metadaten für den Job über ein Einreichungsskript anzugeben, das einfach ein Shell-Skript mit Slurm-spezifischen Anmerkungen ist. Diese Anmerkungen ermöglichen es dir, Ressourcenanforderungen, Scheduling-Parameter und mehr anzugeben. Erstellen wir dafür ein Shell-Skript hello_world.sh.

$ vim hello_world.sh

#SBATCH --job-name=hello-world
#SBATCH --output=hello-world.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=normal

srun hello_world.py
~

Schauen wir uns die Einreichungsdatei an und sehen, was hier passiert.

#SBATCH-Direktiven sind spezifische Anmerkungen, die angeben, welche Anforderungen wir für die Programmausführung haben. Hier kannst du die Menge an Ressourcen angeben – die Anzahl der Knoten, die Anzahl der Aufgaben pro Knoten, die Anzahl der Aufgaben und CPUs pro Knoten und Aufgabe – und andere Optionen wie den Namen der Ausgabedatei. Eine vollständige Liste der Optionen ist in der Dokumentation für Slurm verfügbar.

Jetzt ist es Zeit, unseren Slurm-Job auszuführen. sbatch ist ein Befehl, der eine Einreichungsdatei akzeptiert und den Job zur Ausführung in Slurm in die Warteschlange einreiht.

$ sbatch hello_world.sh

Submitted batch job 63

Lass uns den Status unseres Programms mit dem Befehl squeue überprüfen.

$ squeue

# JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
# 1 main hello_world root R 0:01 1 c1

Sobald der Job abgeschlossen ist, können wir das Ergebnis in der Ausgabedatei überprüfen.

$ cat hello_world_logs.txt
Hello, World!

Verständnisfragen

Gegeben das folgende Slurm-Shell-Skript: Was ist (a) der Name des Jobs, (b) der Name der Python-Datei und (c) der Name der Ausgabedatei? (d) Könnte dieses Skript Quantenressourcen nutzen oder nicht?

vim hello_learner.sh

#SBATCH --job-name=hello-learner
#SBATCH --output=hello-learner.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=quantum

srun hello_learner_qm.py

Antwort:

(a) hello-learner (b) hello-learner_qm.py (c) hello-learner.out (d) Ja, das könnte es. Es verwendet die Quantum-Partition.

Führe ein einfaches Qiskit-„Hello World"-Beispiel in Slurm aus

Als nächstes versuchen wir, auch Quantenressourcen zu nutzen. Erstellen und starten wir ein einfaches „Hello, Qiskit"-Programm, das Quantenressourcen verwendet.

$ vim hello_qiskit.py

# hello_qiskit.py
from qiskit import QuantumCircuit
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import EstimatorV2 as Estimator

# Create a new circuit with two qubits
qc = QuantumCircuit(2)

# Add a Hadamard gate to qubit 0
qc.h(0)

# Perform a controlled-X gate on qubit 1, controlled by qubit 0
qc.cx(0, 1)

observables_labels = ["IZ", "IX", "ZI", "XI", "ZZ", "XX"]
observables = [SparsePauliOp(label) for label in observables_labels]

# switch to QRMI service
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()

backend = service.backend("...")

# Convert to an ISA circuit and layout-mapped observables.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(qc)

# Construct the Estimator instance.

estimator = Estimator(mode=backend)
estimator.options.resilience_level = 1
estimator.options.default_shots = 5000

mapped_observables = [
observable.apply_layout(isa_circuit.layout) for observable in observables
]

# One pub, with one circuit to run against five different observables.
job = estimator.run([(isa_circuit, mapped_observables)])

job_result = job.result()

pub_result = job.result()[0]

print("Result", pub_result)

Hier verwenden wir das Quantum Resource Management Interface (QRMI), ein Slurm-SPANK-Plugin für die Unterstützung von Quantenressourcen und -jobs, das gemeinsam von IBM, Pasqal, dem Hartree Centre und der RPI entwickelt wurde. Wir haben einen einfachen Pauli-2-Design-Circuit mit zufälligen Anfangswerten und einem einfachen Observablen erstellt und führen ihn mit dem Estimator aus, um den Erwartungswert zu erhalten. Um ihn auszuführen, benötigen wir wieder das Einreichungsskript hello_qiskit.sh, das Quantenressourcen als Anforderung enthält.

$ vim hello_qiskit.sh

#SBATCH --job-name=hello-qiskit
#SBATCH --output=hello_qiskit.out
#SBATCH --nodes=1
#SBATCH --ntasks-per-nodes=1
#SBATCH --cpus-per-task=1
#SBATCH --partition=quantum
#SBATCH --gres=qpu:1

srun python /data/ch2/hello_qiskit/hello_qiskit.py
~

Schauen wir uns die Einreichungsdatei an und sehen, was dort passiert. Wir haben eine neue Option: gres. gres ist eine Slurm-Option zur Definition zusätzlicher Rechenressourcen. In unserem Fall wäre diese neue Ressource unsere Quantenressource. Da wir die Ressourcen und die Partition unseres Clusters, auf der Quantenressourcen verfügbar sind, angegeben haben, werden unsere Qiskit-Primitives diese zugewiesenen Ressourcen verwenden, um die Quanten-Payload auszuführen.

Jetzt ist es Zeit, unseren Slurm-Job auszuführen.

$ sbatch hello_qiskit.sh

Dann überprüfen wir den Status unseres Programms mit dem Befehl squeue.

$ squeue
# JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
# 1 main hello_qiskit root R 0:01 1 q1

Wir können Logs und Ergebnisse nach Abschluss des Jobs erkunden.

$ cat hello_qiskit.out | grep Exp
Expectation Value: 0.8372900070983516

Zusammenfassung

Bisher haben wir gelernt, was Rechenressourcen sind und wie man sie nutzt, um Programme in heterogenen Umgebungen auszuführen. Wir haben auch zwei einfache „Hello World"-Programme erstellt und ausgeführt: eines für eine klassische Ressource und eines für eine Quantenressource. Außerdem haben wir gelernt, wie man Shell-Skripte erstellt, um Aufgaben einzureichen und Ergebnisse anzuzeigen.

In der folgenden Lektion werden wir dieses Wissen über die Ressourcensteuerung nutzen, um Programmiermodelle auf die Ressourcen anzuwenden, die wir während der Job-Ausführung erworben haben.

Der gesamte Code und die Skripte aus diesem Kapitel sind in unserem GitHub-Repository für dich verfügbar.