Bend – Eine fortgeschrittene Sprache, die auf GPUs läuft (mit HVM2)
(github.com/HigherOrderCO)- Bend ist eine High-Level-Programmiersprache, die massive Parallelverarbeitung unterstützt
- Im Gegensatz zu Low-Level-Alternativen wie CUDA und Metal bietet Bend das Gefühl und die Fähigkeiten ausdrucksstarker Sprachen wie Python und Haskell
- Enthalten sind schnelle Objektallokation, Higher-Order-Funktionen mit vollständiger Closure-Unterstützung, uneingeschränkte Rekursion und sogar Continuations
- Trotzdem läuft sie auf massiv paralleler Hardware wie GPUs und zeigt je nach Anzahl der Kerne nahezu lineare Geschwindigkeitssteigerungen
- Es sind keinerlei explizite Parallelisierungs-Annotationen nötig: keine Thread-Erzeugung, Sperren, Mutexe oder atomaren Operationen
- Bend wird von der HVM2-Runtime angetrieben
Schnelle Demo
Bend verwenden
Funktioniert derzeit nicht unter Windows; als Alternative muss WSL2 verwendet werden.
- Zuerst muss Rust nightly installiert werden.
- Danach müssen HVM2 und Bend installiert werden:
cargo +nightly install hvm cargo +nightly install bend-lang - Zum Schluss kann eine Bend-Datei geschrieben und mit einem der folgenden Befehle ausgeführt werden:
bend run # Rust-Interpreter verwenden (sequentiell) bend run-c # C-Interpreter verwenden (parallel) bend run-cu # CUDA-Interpreter verwenden (massiv parallel) - Für maximale Performance kann Bend außerdem mit
gen-cundgen-cuin eigenständige C/CUDA-Dateien kompiliert werden. Die Codegenerierung befindet sich jedoch noch in einem frühen Stadium und ist nicht so ausgereift wie moderne Compiler wie GCC oder GHC.
Paralleles Programmieren in Bend
- Um in Bend ein paralleles Programm zu schreiben, muss man ... nichts tun. Es muss nur nicht inhärent sequenziell geschrieben sein.
- Zum Beispiel kann der folgende Ausdruck nicht parallel ausgeführt werden:
weil(((1 + 2) + 3) + 4)+4von+3abhängt und+3von(1+2)abhängt. - Der folgende Ausdruck kann jedoch parallel ausgeführt werden:
weil((1 + 2) + (3 + 4))(1+2)und(3+4)unabhängig voneinander sind. Nach dem Grundprinzip von Bend gilt: Alles, was parallel ausgeführt werden kann, wird parallel ausgeführt.
Beispielcode
-
Als vollständigeres Beispiel betrachten wir den folgenden Code:
# Sortiernetzwerk = Baumrotation def sort(d, s, tree): switch d: case 0: return tree case _: (x, y) = tree lft = sort(d-1, 0, x) rgt = sort(d-1, 1, y) return rots(d, s, lft, rgt) # Teilbaumrotation def rots(d, s, tree): switch d: case 0: return tree case _: (x, y) = tree return down(d, s, warp(d-1, s, x, y)) -
Diese Datei implementiert einen Bitonic Sorter mit unveränderlichen Baumrotationen. Das ist kein Algorithmus, von dem man erwarten würde, dass er auf einer GPU schnell läuft. Durch seinen Divide-and-Conquer-Ansatz ist er jedoch inhärent parallel. Bend führt ihn multithreaded aus. Einige Benchmarks:
- CPU, Apple M3 Max, 1 Thread: 12,15 Sekunden
- CPU, Apple M3 Max, 16 Threads: 0,96 Sekunden
- GPU, NVIDIA RTX 4090, 16k Threads: 0,21 Sekunden
- 57-fache Beschleunigung erreicht, ohne irgendetwas zu tun. Keine explizite Verwaltung von Thread-Erzeugung, Sperren oder Mutexen. Es wurde Bend lediglich angewiesen, das Programm auf einer RTX auszuführen.
Unterstützung für verschiedene parallele Systeme
-
Bend ist nicht auf bestimmte Paradigmen wie Tensoren oder Matrizen beschränkt. Von Shadern bis hin zum Actor-Modell wie in Erlang kann jedes parallele System in Bend emuliert werden.
-
Um zum Beispiel ein Bild in Echtzeit zu rendern, kann für jeden Frame ein unveränderlicher Baum allokiert werden:
# Wenn ein Shader gegeben ist, ein rechteckiges Bild zurückgeben def render(depth, shader): bend d = 0, i = 0: when d < depth: color = (fork(d+1, i*2+0), fork(d+1, i*2+1)) else: width = depth / 2 color = shader(i % width, i / width) return color # Wenn eine Position gegeben ist, eine Farbe zurückgeben # In dieser Demo läuft einfach eine Busy Loop def demo_shader(x, y): bend i = 0: when i < 5000: color = fork(i + 1) else: color = 0x000001 return color # Mit demo_shader ein 256x256-Bild rendern def main: return render(16, demo_shader) -
Es funktioniert tatsächlich. Auch komplexe Algorithmen lassen sich in Bend gut parallelisieren. Kommunikation über große Distanzen erfolgt durch globale Beta-Reduktion (gemäß dem Interaction-Calculus), und sie wird durch die atomaren Linker von HVM2 korrekt und effizient synchronisiert.
Weitere Materialien
- Für den direkten Einstieg sollte man sich Bends GUIDE.md ansehen.
- Für eine Funktionsübersicht sollte man FEATURES.md ansehen.
- Um die Technologie hinter Bend zu verstehen, sollte man das Paper zu HVM2 lesen.
- Bend wird bei HigherOrderCO.com entwickelt – tritt dem Discord bei.
Meinung von GN⁺
- Vereinfachung des parallelen Programmierens: Bend vereinfacht paralleles Programmieren stark, sodass selbst Junior-Software-Ingenieure leicht darauf zugreifen können. Das senkt die Einstiegshürde für paralleles Programmieren erheblich.
- Unterstützung verschiedener Hardware: Bend kann nicht nur auf CPUs, sondern auch effizient auf GPUs laufen und ist dadurch in unterschiedlichen Hardware-Umgebungen einsetzbar.
- Ausdrucksstarke Sprache: Durch die Verbindung der Stärken von Python und Haskell lässt sich sehr ausdrucksstarker Code schreiben. Das verbessert Lesbarkeit und Wartbarkeit.
- Codegenerierung in frühem Stadium: Die Codegenerierung von Bend befindet sich derzeit noch in einer frühen Phase und kann im Vergleich zu ausgereiften Compilern in der Performance zurückfallen. Hier besteht künftig Verbesserungsbedarf.
- Unterstützung verschiedener paralleler Systeme: Bend ist nicht auf ein bestimmtes Paradigma beschränkt und unterstützt verschiedene parallele Systeme, was flexible Programmierung ermöglicht. Dadurch kann Bend in vielen Anwendungsbereichen eingesetzt werden.
1 Kommentare
Hacker-News-Meinungen
Zusammenfassung ausgewählter Hacker-News-Kommentare
Leistungsvergleich zwischen Python und PyPy
Positives Feedback
Kritische Stimmen
Erwartungen an paralleles Programmieren
Leistungsvergleich
Erwartete Weiterentwicklung des Projekts
Skeptische Sichtweise
Positive Perspektive
Sprachliche Eigenschaften von Bend