Jeremy Howard beschreibt die Funktionalitäten und Spezifika von Mojo in seinem Blog:
Sicherlich erinnern sich viele noch die Einführung von Visual Basic, das damals noch ein Programm für MS DOS war. Vorher war das Schreiben von Programmen extrem komplex und ich konnte nicht viel mehr als einfache Demoprogramme erstellen. Aber mit VB konnte ich einen Button auf dem Bildschirm zeichnen, eine einzelne Zeile Code eingeben, die ausgeführt werden sollte, wenn auf diesen Button geklickt wurde, und schon hatte ich eine vollständige Anwendung, die ich nun ausführen konnte. Diese Erfahrung war so unglaublich, dass ich dieses Gefühl nie vergessen werde.
Das Programmieren in Mojo, einer neuen Programmiersprache von Modular, war das zweite Mal in meinem Leben, dass ich dieses Gefühl hatte.
Bevor ich meine Begeisterung für Mojo erklären kann, muss ich zuerst ein paar Dinge über Python sagen.
Python ist die Sprache, die ich für fast all meine Arbeit in den letzten Jahren verwendet habe. Es ist eine wunderschöne Sprache. Sie hat einen eleganten Kern, auf dem alles andere aufgebaut ist. Diese Herangehensweise bedeutet, dass man mit Python absolut alles machen kann. Dies hat jedoch einen Nachteil: die Performance.
Python ist tausendfach langsamer als Sprachen wie C++. Das macht es unpraktisch, Python für leistungskritische Teile des Codes zu verwenden. Der Trick von Python besteht jedoch darin, auf Code in schnelleren Sprachen zugreifen zu können. Daher lernen Python-Programmierer, Python nicht für die Umsetzung von leistungskritischen Abschnitten zu verwenden, sondern dafür Python-Umgebungen über C, FORTRAN, Rust, etc. Code zu nutzen.
Dieser “Zweisprachen”-Ansatz hat ernste Nachteile. Beispielsweise müssen KI-Modelle oft von Python in eine schnellere Implementierung umgewandelt werden. Es ist allerdings sehr schwierig, die bereitgestellte Version des Codes zu debuggen.
Chris Lattner hat viele Projekte geschaffen, auf die wir uns heute alle verlassen – auch wenn wir vielleicht noch nicht von allem gehört haben, das er gebaut hat! Im Rahmen seiner Doktorarbeit begann er mit der Entwicklung von LLVM, das grundlegend veränderte, wie Compiler erstellt werden. Er startete dann Clang, einen C- und C++-Compiler, der auf LLVM basiert und von den meisten bedeutenden Softwareentwicklern der Welt verwendet wird.
Chris sah jedoch, dass C und C++ die Leistungsfähigkeit von LLVM nicht wirklich voll ausschöpfen. Deshalb entwarf er während seiner Tätigkeit bei Apple eine neue Sprache namens „Swift“. Swift ist heute eine der am meisten verwendeten Programmiersprachen, insbesondere weil es heute die Hauptsprache zur Erstellung von iOS-Apps für iPhone, iPad, MacOS und Apple TV ist.
Unglücklicherweise hat die Kontrolle von Swift durch Apple dazu geführt, dass es außerhalb der abgeschotteten Apple-Welt nicht wirklich glänzen konnte. Chris leitete für eine Weile ein Team bei Google, um Swift aus seiner Apple-Komfortzone zu holen und es zu einem Ersatz für Python in der AI-Modellentwicklung zu machen.
Während seiner Zeit bei Google entwickelte Chris ein anderes Projekt, das sehr erfolgreich wurde: MLIR. MLIR ist ein Ersatz für LLVMs IR für das moderne Zeitalter des many-core computing und der KI-Workloads. Es ist entscheidend für die vollständige Nutzung der Leistungsfähigkeit von Hardware wie GPUs, TPUs und den immer häufiger hinzugefügten Vektoreinheiten von Serverklasse-CPUs.
Wenn also Swift “Synthentic Sugar für LLVM” war, was ist dann “Synthentic Sugar für MLIR”? Die Antwort ist: Mojo! Mojo ist eine brandneue Sprache, die darauf ausgelegt ist, die Vorteile von MLIR voll auszuschöpfen. Und Mojo ist auch Python.
Ein wichtiger Trick in Mojo besteht darin, dass Sie als Entwickler jederzeit einen schnelleren “Modus” aktivieren können. Sie müssen dabei die Art jeder Variable genau deklarieren, und als Ergebnis kann Mojo optimierten Maschinencode erstellen.
Es hat bereits hunderte von Versuchen über Jahrzehnte gegeben, Programmiersprachen zu schaffen, die prägnant, flexibel, schnell, praktisch und einfach in der Anwendung sind – leider ohne großen Erfolg. Dennoch scheint es, als hätte Modular es geschafft. Wie haben sie das geschafft? Wir haben ein paar Hypothesen:
Beide Vermutungen sind falsch. In der Tat wurde die Demopalette in nur wenigen Tagen erstellt. Modular ist ein relativ kleines Start-up, das erst ein Jahr alt ist, und nur ein Teil des Unternehmens arbeitet tatsächlich an der Mojo-Sprache. Das Mojo-Entwicklungsteam besteht nur aus wenigen Personen, die erst vor kurzer Zeit mit der Arbeit begonnen haben.
Der Schlüssel ist, dass Mojo auf sehr mächtigen Grundlagen aufbaut. Nur wenige Softwareprojekte verbringen genügend Zeit, um die richtigen Grundlagen zu errichten. Mit der Zeit wird es immer schwieriger, Funktionen hinzuzufügen und Fehler zu beheben. In einem gut gestalteten System ist jedoch jede Funktion einfacher hinzuzufügen, schneller und hat weniger Fehler, weil die Grundlagen immer besser und besser werden. Mojo ist in dieser Hinsicht ein gut gestaltetes System.
Im Zentrum steht MLIR, das Chris Lattner ursprünglich bei Google mitinitiiert hat. Er hatte erkannt, welche Grundlagen für eine “KI-Ära-Programmiersprache” notwendig wären und konzentrierte sich auf deren Entwicklung.
Ein weiterer Schlüssel zur schnellen Entwicklung von Mojo ist die Entscheidung, Python als Syntax zu verwenden. Die Entwicklung und Iteration der Syntax ist einer der fehleranfälligsten, komplexesten und umstrittensten Teile der Entwicklung einer Sprache. Indem sie dies einfach an eine existierende Sprache auslagerten (Python), wird ein Großteil dieser Komplexität vermieden!
Der nächste Schritt bestand darin, eine minimale Python-ähnliche Möglichkeit zu schaffen, MLIR direkt aufzurufen. Mit dieser Basis konnten die Mojo-Entwickler fast von Anfang an Mojo’s verwenden und weiterentwickeln.
Dies ist sehr ähnlich zu Julia, das auf einem minimalen LISP-ähnlichen Kern basiert. Fast alles in Julia ist mit Julia selbst aufgebaut.
Letztendlich ist dies der Grund, optimistisch in die Zukunft von Mojo zu schauen. Obwohl dieses Projekt noch in den Anfängen steckt, glaube ich, basierend auf dem, was ich in den letzten Monaten gesehen habe, dass es sich schneller und weiter entwickeln wird, als die meisten von uns erwarten…
Eines der faszinierendsten Dinge möchte ich bis zum Schluss aufbewahren: das Deployment. Zurzeit müssen Sie, wenn Sie Ihr cooles Python-Programm an einen Freund weitergeben möchten, diesen erst Python installieren lassen! Alternativ könnten Sie eine riesige Datei verschicken, die die gesamte Python-Infrastruktur und die von Ihnen verwendeten Bibliotheken enthält.
Da Python eine interpretierte Sprache ist, hängt das Verhalten Ihres Programms von der genauen Python-Version, den vorhandenen Bibliotheksversionen und der gesamten Konfiguration ab. Um diesem Wartungs-Albtraum zu entkommen, hat die Python-Community ein paar Optionen für die Installation von Python-Anwendungen festgelegt: Umgebungen, die eine separate Python-Installation für jedes Programm haben oder Container, die für jede Anwendung fast ein ganzes Betriebssystem bereitstellen. Beide Ansätze führen zu viel Verwirrung und zu höherem Aufwand beim Entwickeln und Bereitstellen von Python-Anwendungen.
Vergleichen Sie dies mit der Bereitstellung einer statisch kompilierten C-Anwendung: Sie können das kompilierte Programm einfach zum direkten Herunterladen bereitstellen. Es kann lediglich 100k groß sein und wird schnell geladen und ausgeführt.
Dann gibt es noch den Ansatz von Go, der keine kleinen Anwendungen wie C generieren kann, sondern in jede verpackte Anwendung eine “Laufzeit” einfügt. Dieser Ansatz ist ein Kompromiss zwischen Python und C, benötigt immer noch zig Megabyte für eine Binärdatei, bietet aber eine einfachere Bereitstellung als Python.
Als kompilierte Sprache ist die Bereitstellung von Mojo im Grunde die gleiche wie bei C. Zum Beispiel ist ein Programm, das eine von Grund auf neu geschriebene Version von matmul enthält, ungefähr 100k groß.
Das bedeutet, dass Mojo viel mehr ist als eine Sprache für AI/ML-Anwendungen. Es ist tatsächlich eine Version von Python, die es uns ermöglicht, schnelle, kleine, leicht bereitstellbare Anwendungen zu schreiben, die alle verfügbaren Kerne und Beschleuniger nutzen!
Mojo ist nicht der einzige Ansatz, um die Leistungs- und Bereitstellungsprobleme von Python zu lösen. Bei den Sprachen ist Julia vielleicht die stärkste Alternative. Es hat viele Vorteile von Mojo und viele großartige Projekte sind bereits damit realisiert.
Julias größte Herausforderung entsteht aus seiner umfangreichen Laufzeit, die letztendlich aus der Entscheidung für die Verwendung der Speicherbereinigung in der Sprache resultiert. Zudem kann der in Julia verwendete Multidispatch-Ansatz viele Möglichkeiten für coole Anwendungen eröffnen, jedoch auch die Aufgabe für Entwickler erschweren.
Unter Python ist Jax wahrscheinlich die bekannteste Lösung, die eine domänenspezifische Sprache (DSL) mit Python erstellt. Jax erbt die Beschränkungen sowohl von Python (z.B. kann die Sprache keine Strukturen darstellen, Speicher direkt zuweisen oder schnelle Schleifen erzeugen) als auch von XLA.
Interessant für Python sind auch Numba und Cython. Numba verwendet einen speziellen Dekorateur, um eine Python-Funktion in optimierten Maschinencode mithilfe von LLVM zu übersetzen. Cython ist ähnlich, bietet jedoch eine Python-ähnliche Sprache, die einige Merkmale von Mojo aufweist, und konvertiert diesen Python-Dialekt in C, der dann kompiliert wird.
Allerdings bevorzuge ich eine Sprache, die so elegant wie Python und so schnell wie fachmännisch geschriebenes C ist, mir ermöglicht, alles von dem Anwendungsserver, zur Modellarchitektur und dem Installer in einer Sprache zu schreiben, und es mir erlaubt, meinen Code direkt in der Sprache, in der ich ihn geschrieben habe, zu debuggen und zu profilieren.
Würde Ihnen eine solche Sprache gefallen?