Lattner Builds Mojo to Erase Python's C Bottleneck Across AI Chips

Mojo Lang - Tomorrow's High Performance Python? (with Chris Lattner) — Developer Voices

Developer Voices

Mojo eliminates computing's two-language divide by pairing Python syntax directly with MLIR primitives, allowing developers to target specialized hardware without rewriting critical kernels in C++ or CUDA.

AI-assisted summary of Mojo Lang - Tomorrow's High Performance Python? (with Chris Lattner) — original source. Check the original for full context.

Source published:

Key ideas

  • Mojo bridges Python's performance bottleneck by fundamentally redesigning the compiler architecture around MLIR, emitting intermediate representations directly during parsing to target CPUs, GPUs, and specialized AI accelerators. (3:44)
  • By adopting Python syntax, Mojo eliminates the classic 'two-language problem' in machine learning, allowing developers to write native systems code and bare-metal loops without dropping down into C, C++, or Fortran extensions. (17:15)
  • Mojo re-engineers memory management by utilizing eager destruction and opt-in borrow checking, automatically freeing memory immediately upon a variable's last use to optimize large tensor workloads and preserve tail-call elimination. (50:55)
  • Modular open-sourced Mojo's standard library under the Apache 2.0 license with patent grants, rapidly scaling to over 175,000 developers and direct interoperability with existing CPython libraries. (77:04)

Detailed notes

## Background This episode was published on YouTube by Developer Voices (hosted by Kris Jenkins) on May 1, 2024. Featuring LLVM and Swift creator Chris Lattner, the interview explores why the Mojo programming language was created, how it packages CPU- and GPU-level performance into a Python-compatible syntax, and how it bridges high-level scripting with low-level compiler infrastructure like MLIR.

## TL;DR Modular created Mojo to solve the modern hardware crisis and eliminate Python's historical 'two-language problem' by unifying high-level dynamic syntax with bare-metal systems performance. Rather than wrapping Python in another embedded DSL, Mojo was built from the ground up on MLIR, emitting intermediate representations directly to expose hardware primitives, SIMD instructions, and tensor accelerators. It introduces sound, unboxed machine types, compile-time metaprogramming (comptime), eager destruction, and an opt-in borrow checker that refines ownership models seen in Rust and Swift. By enabling seamless bidirectional Python interoperability alongside zero-cost systems abstractions, Mojo allows developers to transition smoothly from rapid prototyping to high-performance AI deployment and systems programming.

## Atmosphere & style The conversation has the engaging, collegial vibe of two seasoned systems engineers diving into deep technical mechanics over a whiteboard. Chris Lattner speaks with pragmatic, battle-tested candor, sharing war stories about the psychological toll of implementing the C++ standard and demystifying why compiler dogmas must evolve for modern silicon. Kris Jenkins serves as an enthusiastic, insightful interlocutor who grounds high-level compiler theory in developer ergonomics and pushes back against elitist gatekeeping. The tone is deeply optimistic about computing's future, balancing rigorous technical breakdowns with an approachable, empowering message for everyday Python programmers.

## Bulletin - [03:44](https://www.youtube.com/watch?v=JRcXUuQYR90&t=224s) Mojo bridges Python's performance bottleneck by fundamentally redesigning the compiler architecture around MLIR, emitting intermediate representations directly during parsing to target CPUs, GPUs, and specialized AI accelerators. - [17:15](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1035s) By adopting Python syntax, Mojo eliminates the classic 'two-language problem' in machine learning, allowing developers to write native systems code and bare-metal loops without dropping down into C, C++, or Fortran extensions. - [50:55](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3055s) Mojo re-engineers memory management by utilizing eager destruction and opt-in borrow checking, automatically freeing memory immediately upon a variable's last use to optimize large tensor workloads and preserve tail-call elimination. - [01:17:04](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4624s) Modular open-sourced Mojo's standard library under the Apache 2.0 license with patent grants, rapidly scaling to over 175,000 developers and direct interoperability with existing CPython libraries.

## Key takeaways - [00:00](https://www.youtube.com/watch?v=JRcXUuQYR90&t=0s) Solving Python's performance limits requires rethinking the underlying compiler stack from the hardware level up, rather than repeating breaking syntax migrations like Python 2 to 3. - [03:44](https://www.youtube.com/watch?v=JRcXUuQYR90&t=224s) The plateau of Dennard scaling and Moore's Law makes specialized hardware, such as matrix accelerators and tensor cores, mandatory for modern performance. - [06:31](https://www.youtube.com/watch?v=JRcXUuQYR90&t=391s) MLIR replaces traditional monolithic intermediate representations like LLVM IR with a multi-level hierarchy that Mojo targets directly without an AST intermediate step. - [11:05](https://www.youtube.com/watch?v=JRcXUuQYR90&t=665s) Mojo adopted Python syntax to respect developer muscle memory, accelerate adoption in the AI ecosystem, and avoid contentious syntax debates. - [17:15](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1035s) The Python two-language problem forces high-performance libraries like NumPy to split across Python and C/C++, whereas Mojo delivers bare-metal performance in unified syntax. - [19:27](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1167s) Python can be formally conceptualized as a static language with a single dynamic reference type (PythonObject), which Mojo exposes to allow progressive, sound typing down to raw machine types. - [23:30](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1410s) Mojo replaces internal compiler magic by implementing fundamental primitives like integers and floats as standard library structs wrapping raw MLIR operations. - [28:38](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1718s) Compile-time metaprogramming enables Mojo to inspect hardware capabilities at compile time, generating specialized SIMD instructions while preserving portable generic fallbacks. - [34:58](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2098s) The MAX Engine treats Mojo kernels as transparent white boxes via MLIR, enabling cross-operator fusion that opaque proprietary stacks like CUDA cannot achieve. - [40:35](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2435s) The traditional rule against writing nested loops in Python is obsolete in Mojo, where loops compile to zero-overhead machine code capable of directly invoking hardware matrix units. - [42:38](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2558s) Mojo supports Zig-style compile-time execution (comptime), running standard functions and dynamic heap allocations during compilation to bake precomputed tables into binaries. - [50:55](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3055s) Unlike Rust's lexical scope drops, Mojo implements eager destruction immediately after a value's last use, preventing memory pressure in 4GB+ GPU tensor allocations. - [52:41](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3161s) Mojo guarantees zero implicit memory copies during moves and avoids Rust-style pinning by tracking ownership and concrete identity strictly at compile time. - [55:19](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3319s) Value semantics enable Mojo to provide safe in-place data mutations while maintaining functional programming immutability guarantees externally. - [01:11:03](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4263s) Mojo decouples mathematical 2D tile algorithms from hardware-specific execution schedules, allowing higher-order combinators to orchestrate caching and striding across CPUs and GPUs. - [01:17:04](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4624s) Mojo seamlessly executes existing CPython libraries side-by-side with compiled code without requiring custom foreign function interface (FFI) bindings. - [01:21:00](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4860s) Mojo's overarching goal is to demystify systems programming, empowering Python developers to master low-level hardware performance without shifting to alien programming ecosystems.

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=JRcXUuQYR90&t=0s) Flipping the Python Performance Question on its Head

Kris Jenkins opens the episode by questioning the conventional wisdom around language performance. It seems inherently improbable that Python could ever transform into a high-performance, parallel programming language on its own; bridging that gap involves fundamental architectural shifts far more drastic than the painful migration from Python 2 to Python 3. Jenkins flips the premise entirely: rather than attempting to force high-performance parallelism into Python, could an inherently high-performance, parallel, compiler-level language simply adopt Python's syntax? Starting low in the compiler stack to solve the hard performance and hardware problems first, and then building up into user space with familiar syntax, offers a much more viable path forward.

That bottom-up philosophy is precisely the premise behind Mojo, a new language designed by Chris Lattner. Lattner's pedigree in systems architecture is unmatched: he created LLVM, developed the Clang C/C++ compiler, and created Swift. With that background, he is uniquely equipped to bridge the entire computing stack from high-level Python syntax down to the bare metal of CPUs and GPUs. Mojo aims to offer a gradual type system, first-class parallelism, and direct programmer access to compiler instructions—delivering powerful systems programming primitives wrapped in friendly, familiar clothing.

[01:51](https://www.youtube.com/watch?v=JRcXUuQYR90&t=111s) Nights, Weekends, and Surviving C++

Welcoming Lattner to the podcast, Jenkins remarks on his formidable resume, noting that LLVM began as Lattner’s master’s research project. Rather than resting on his laurels, Lattner continued pushing boundaries. Clang and Swift both started as nights-and-weekends side projects while he was working on other primary responsibilities during the day. In the case of Swift, Lattner had spent a year and a half developing it on his own time while his day job involved wrapping up the Clang C and C++ compiler.

Implementing C++ was an informative yet punishing technical ordeal, and Lattner confesses that building Swift was almost a psychological coping mechanism to imagine a better world. As Chris Lattner explains: “C++ is a very interesting, informative language, very challenging technical problem to implement. And at least for me, I could not survive that experience without thinking maybe there could be something new and better.” Jenkins sympathizes from a user perspective, recalling that after years of struggling with Objective-C, Swift felt like a lifeline thrown right as he was getting off the boat.

[03:44](https://www.youtube.com/watch?v=JRcXUuQYR90&t=224s) Hardware Specialization and Starting with a Headless Compiler

Given how exhausting and difficult language design is, Jenkins asks why Lattner would willingly subject himself to the ordeal once again. Lattner admits he initially resisted building a new language because he knows firsthand the monumental effort required. When designing Swift or his earlier work on OpenCL, he began from the user-facing syntax, prioritizing language features like autoclosures and higher-order functional programming before compiling them down through LLVM. With Mojo and his work at Modular, however, the problem was inverted: the driving requirement was figuring out how to make modern hardware and GPUs "go brrr."

For decades, software performance benefited from Moore's Law and Dennard scaling; a new CPU arrived every year, and recompiling legacy code made it run faster with minimal compiler tweaks. Today, general CPU scaling has plateaued, replaced by an explosion of specialized accelerators: GPUs, custom matrix engines, and vector hardware utilizing exotic data formats like BF16. To rationalize this fragmented landscape, Modular did not begin by writing a language spec or grammar. Instead, they built a sophisticated code generator without any frontend at all—replacing core components of LLVM, generating optimized loop nests, and hand-writing intermediate representation (IR) to validate the compilation stack before even contemplating syntax.

```mermaid flowchart TD accTitle: Evolution of Modular's Compilation Architecture accDescr: Diagram showing how Modular transitioned from pure IR and code generation to a complete language with Mojo.

subgraph Phase1["Phase 1: Proof of Concept"] HwTargets["Hardware Accelerators\n(GPUs, Matrix Units, BF16)"] CustomCodegen["Novel Loop Synthesis & Codegen Engine"] HandwrittenIR["Hand-Written MLIR Text Files"] HandwrittenIR --> CustomCodegen CustomCodegen --> HwTargets end

subgraph Phase2["Phase 2: Mojo Frontend"] PythonSyntax["Python-Compatible Syntax\n(Mojo Language)"] DirectParser["Parser / Semantic Analysis"] DirectParser -->|"emits directly"| HandwrittenIR PythonSyntax --> DirectParser end ```

[06:31](https://www.youtube.com/watch?v=JRcXUuQYR90&t=391s) MLIR: Replacing the "One IR to Rule Them All" Dogma

To build this headless code generator, Lattner turned to MLIR (Multi-Level Intermediate Representation), a compiler infrastructure framework he created in 2018 that is now part of the LLVM umbrella. LLVM IR served the industry for roughly 25 years under the philosophy that a single, unified IR should rule them all. While that worked well for code that mapped closely to C—which Lattner jokes was essentially "C with vectors plus exceptions" or "C with vectors plus debug info"—it breaks down when compiling for complex accelerators and GPUs. Modern hardware compilers require multiple, distinct levels of progressive lowering and domain-specific abstraction, akin to the multi-stage pipelines found in compilers like GHC for Haskell.

MLIR functions as a modular toolkit that gives compiler engineers the scaffolding—parsers, printers, pass managers, diagnostic bisecting tools, and customizable type systems—to build domain-specific intermediate representations rapidly. While MLIR possesses a human-readable text format, Lattner notes that writing hundreds of lines of IR by hand is a grueling, painful process suitable only for proving out a concept. Interestingly, unlike conventional compilers that parse source text into an Abstract Syntax Tree (AST) before lowering to intermediate code, Mojo avoids a traditional AST entirely: its parser directly synthesizes MLIR.

- LLVM IR operates at a single, relatively low level of abstraction modeled around C-like semantics and vector extensions. - MLIR is domain-independent; it has been applied to machine code generation, machine learning acceleration, and hardware synthesis tooling. - Mojo bypasses the standard AST phase found in most language architectures, emitting MLIR directly during parsing.

[09:17](https://www.youtube.com/watch?v=JRcXUuQYR90&t=557s) Putting "Porcelain on the Plumbing"

Once the underlying code generation engine proved its viability, Modular faced the challenge of exposing it to developers—putting what Jenkins calls the "porcelain on the plumbing." The team evaluated several paths: building an embedded domain-specific language (DSL) inside an existing host like Python using decorators and AST-walking; constructing a source-to-source transpiler; or committing to building a standalone programming language.

Despite knowing how punishing full-scale language development can be, the team recognized that developers in machine learning and systems programming are drowning under the complexity of current toolchains. An embedded DSL or fragile AST walker would fail to provide the deep control, ergonomics, and unified execution model necessary for high-performance computing. As Chris Lattner reflects: “And so we decided, okay, let's do the hard thing. Let's eyes wide open. We understand how hard it is to build a programming language. Let's do that.” Choosing Python compatibility as that user-facing layer allowed them to meet the AI and accelerator community exactly where they already work.

[11:05](https://www.youtube.com/watch?v=JRcXUuQYR90&t=665s) Why Building a New Language Is Usually a Bad Idea

Chris Lattner opens with a candid warning about the immense hidden costs of language creation: “tradeoff is worth it. And let me tell you why it's a bad idea to build a programming language.” Beyond defining a grammar and writing a compiler, the creators must construct an entire developer universe from scratch. That means code formatters, debuggers, a library ecosystem, package managers, language servers (LSP), and a dedicated developer community rallying on Slack channels. Having weathered that exact gauntlet with Swift, Lattner recalls the grueling energy spent bikeshedding every tiny syntactic detail.

```mermaid flowchart TD accTitle: The Hidden Toll of Building a Language accDescr: Diagram contrasting the narrow core tasks of a language creator against the massive surrounding ecosystem requirements.

subgraph Core["Core Language Tasks"] G["Grammar"] C["Compiler Design"] end

subgraph Tooling["Tooling & Infrastructure"] F["Code Formatters"] D["Debuggers"] LSP["Language Server Protocol (LSP)"] PM["Package Manager"] end

subgraph Community["Ecosystem & Community"] LIBS["Library Ecosystem"] COMM["Developers / Community"] COMMS["Slack & Discord Channels"] end

Core --> Tooling Tooling --> Community ```

When conceiving Mojo, Lattner wanted to aggressively de-risk the venture by meeting developers where they already reside. In the machine learning and artificial intelligence ecosystem, that place is unambiguously Python. As Lattner puts it: “And in AI in particular, Python won. Like Python is nothing. Yeah. And so everybody uses Python.” Trying to market an entirely foreign syntax with curly braces instead of indentation fails to respect the muscle memory of hundreds of millions of developers. Adopting Python's established syntax completely bypassed the need to bikeshed basic language semantics from first principles, letting the Modular team focus their engineering energy directly on hard computational problems.

- Python's syntactic quirks, like its postfix ternary expression (`x if cond else y`), were retained despite personal taste because preserving compatibility and existing programmer muscle memory outweighed aesthetic debates. - Kris Jenkins observes that adopting Python means “most of those early decisions are made for you.”

[13:24](https://www.youtube.com/watch?v=JRcXUuQYR90&t=804s) Mission-Driven Focus: AI Accelerators vs. Gaming

Kris Jenkins asks why Modular didn't target PlayStation 5 developers and the high-performance gaming industry, where immense budgets and hardware demands exist alongside a thirst for GPU optimizations. Lattner explains that Modular is intensely mission-driven around AI, accelerators, and GPUs—a domain he has lived in for over seven years. While gaming remains lucrative, Lattner felt the hardware accelerator bottleneck in AI was the acute, burning problem to solve.

At the same time, Mojo is engineered without loss of generality; it is a full general-purpose programming language. Community members are already using it to write GUI libraries, web servers, and systems tools. Lattner highlights that if another language had already solved these unified accelerator challenges, they happily would have used it instead of undertaking the massive effort of creating Mojo: “there is no language out there that does what Mojo does. And so solving for those, you know, that was another option is just use somebody else's language, right? And so if there's another language out there, it would be great to just not have to do all this work, because we could get on with life and focus on other parts of the problem.” Even with the primary AI focus, Modular has already attracted talent from the gaming industry onto their team.

[14:56](https://www.youtube.com/watch?v=JRcXUuQYR90&t=896s) The Python 2 to 3 Disaster and Mojo's Mountain

Addressing how Mojo feels to an everyday Python programmer, Lattner clarifies that Mojo is roughly halfway through its complete development roadmap. When finished, it aims to be a complete superset of Python. The design is deliberately shaped to avoid repeating the infamous Python 2 to Python 3 transition, which fractured the ecosystem: “just about killed everybody involved sucked energy out of the community for 15 years, it was it was kind of a gigantic mess.” That disaster occurred because the two versions could not easily interoperate, forcing an impossible, all-or-nothing rewrite.

Drawing on his background transitioning Apple developers from Objective-C to Swift, Lattner stresses progressive migration:

```mermaid flowchart LR accTitle: Progressive Migration Strategy accDescr: Chart illustrating how Mojo enables mixed codebases across hardware, systems, and dynamic layers.

subgraph Execution["Unified Language Strategy"] direction TB CUDA["CUDA replacement<br/>(Accelerators & GPUs)"] RUST["Rust replacement<br/>(Systems & Safety)"] PY["Full Python superset<br/>(Dynamic, High-Level APIs)"] end

CUDA --> RUST --> PY ```

By allowing bidirectional calling between languages, Swift enabled developers to keep old Objective-C dependencies intact while writing fresh application UIs in Swift. Mojo brings that exact progressive ethos to Python. Even today, developers can directly import and execute arbitrary standard Python libraries alongside Mojo code. Mojo is ascending an enormous mountain: starting at the base by replacing CUDA for accelerators, moving into systems programming to serve as a high-performance alternative to Rust, and finally completing the high-level dynamic runtime features that Python developers love.

[17:15](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1035s) Eliminating the "Two-Language Problem" and C Bindings

Python has long disguised what Lattner calls its "dark truth": while offering high-level object-oriented elegance, nearly all real performance-critical code is written under the hood in C, C++, or Fortran. Libraries like NumPy merely act as Python wrappers over low-level libraries like Intel MKL. This classic "two-language problem" forces engineers to leave the Python environment whenever speed matters.

Mojo bridges this divide by delivering a unified language built around a progressive type system with real native types, backed by MLIR-era next-generation compiler infrastructure. Python programmers can write hardware-speed implementations without switching ecosystems. Regarding Python’s C API interop, Lattner explains that Mojo can already execute Python C extensions directly through its Python runtime interop layer, and Mojo also possesses its own direct C FFI to call native C code without Python's object overhead. Modular is still actively considering how much of Python's low-level, internal C object model to mirror natively, versus encouraging authors to write high-performance libraries directly in Mojo.

- Python's architecture mirrors Objective-C: an elegant, dynamic object runtime backed by high-performance C layers. - Mojo's compiler infrastructure draws from decades of compiler evolution to provide both static efficiency and dynamic flexibility.

[19:27](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1167s) Mojo's Perspective on Types: Python as a One-Type Language

When Kris asks Lattner to clarify what Modular means by a "progressive type system" versus a "gradual type system," Lattner prefaces his explanation with an engineer’s humility: “I'm also, by the way, an engineer, I'm not a mathematician. Okay, so just as a disclaimer.” He then deconstructs how typed systems reconcile with Python by challenging common perceptions of Python's type architecture:

> “And if you ask a lay programmer, they would typically tell you, oh, well, Python doesn't have types. Right. And then if you talk to a more advanced developer, they'd say, oh, it has dynamic types. Right. And so there's a list, there's a dictionary, there's this stringer and int, but it's all runtime. Right. Yeah. As somebody who knows programming languages and likes some static languages now and then, we can say Python has one type. And that one type is a reference to a Python object. And because there's one type in Python, you never spell it. And so that's how I would say Python is it actually has a static type system. It just has one type.”

Under this lens, Python code is already uniform. In Mojo, that underlying base type is explicitly surfaced under the hood as `PythonObject` (with decisions pending on whether to eventually shorten it simply to `object`), establishing the foundation from which explicit, hardware-native types can be introduced progressively.

[21:14](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1274s) Progressive Typing vs. Type Hints: Real Types for Systems Programmers

Chris Lattner explains how Mojo approaches the transition between dynamic and static typing without falling into the trap of superficial "type hints." In Mojo, dynamic data is represented by a specific type known as `PythonObject`. When a developer explicitly declares a variable as an `Int` or a `String`, it is not merely a hint—it is an entirely distinct, unboxed type residing directly on the stack, sized to the machine's native word, and operating just like an integer in C or C++. Lattner emphasizes that Mojo targets CPU and GPU numeric programmers who demand absolute, predictable control over low-level hardware optimizations. These developers reject speculative JIT mechanisms that try to guess and devirtualize dynamic code. Instead, Mojo embraces what Lattner calls the "Rust ideal" of predictable performance: getting the compiler completely out of the developer's way while still permitting them to opt out into dynamic behavior when desired.

Kris Jenkins asks if this is analogous to PureScript or TypeScript, where a foreign, untyped value from JavaScript is simply cast by assertion and treated as a string, regardless of what lies beneath. Lattner pushes back strongly against that comparison. He clarifies that TypeScript and Python treat the universe as fundamentally untyped, using type hints primarily for linters or error messages. In Mojo, conversions between dynamic types like `PythonObject` and native types like `Int` are fully checked at runtime.

As Lattner states: “It’s not that conversion is checked, and so there’s no like, trust me, it’s going to be okay typing, it’s actually typed, and this is actually very important.” Because these conversions are sound and checked, the entire language composes cleanly through its type system.

- Mojo provides a sound type system rather than purely decorative type annotations. - `PythonObject` is an explicit type within the static system rather than a compiler blind spot. - High-performance numeric engineers receive zero-overhead, stack-allocated machine types with predictable execution.

---

[23:30](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1410s) Pushing Magic Out of the Compiler and Into Libraries

When examining Mojo's static type system, Lattner describes it as simultaneously "boring" and "boundary pushing." The boring aspect is intentional: Mojo borrows proven concepts from modern typed functional languages, adopting generic, higher-order type system mechanics inspired by category theory, Rust traits, and Swift protocols. However, the radical difference lies in Mojo's philosophy of stripping magic out of the compiler and moving it into standard libraries.

Lattner critiques older systems languages like C++ to illustrate this division of responsibility. In C++, historical baggage led to an arbitrary divide: complex numbers are implemented as a library template (`std::complex`), while basic types like `float` and `double` are baked directly into the compiler. Furthermore, C++ restricts library authors by refusing to allow overloading of critical primitives—most notoriously `operator.`, which prevents the creation of true smart references and, as Lattner notes, has driven C++ creator Bjarne Stroustrup crazy for decades. In Mojo, fundamental types like `Int` and `Float` are not language built-ins at all; they are plain structs implemented entirely in the library. This design discipline forces the language syntax to remain minimal while empowering library authors with the exact same tools used to construct the language's core primitives.

Jenkins likens this discovery to his early days learning Haskell, where he was stunned to realize that booleans were not an intrinsic primitive of the language, but rather a user-definable type alongside everything else. Lattner agrees, noting that by balancing the language-versus-library boundary this way, Mojo stays flexible and dynamic enough for Python users while remaining deeply expressive at the foundational level.

As Lattner puts it: “And so in Mojo, we take a very aggressive approach on this, which is say, push everything we can into libraries and push the magic out of the compiler.”

```mermaid flowchart TD accTitle: Compiler and Library Separation in Mojo accDescr: Diagram illustrating how Mojo pushes primitives into libraries backed by MLIR rather than hardcoding them in the compiler.

subgraph UserSpace["High-Level Library Space"] A["Python-style Ergonomics<br/>(Dunder methods, Structs)"] B["Core Types<br/>(Int, Float, SIMD, Complex)"] end

subgraph CoreEngine["Low-Level Compiler Primitives"] C["MLIR / LLVM Primitives"] D["Hardware Acceleration<br/>(Tensor Cores, SIMD, GPUs)"] end

A --> B B --> C C --> D ```

---

[26:13](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1573s) Turtles All the Way Down: Zero-Cost Abstractions and MLIR

Jenkins raises the central dilemma of library-defined primitives: how can Mojo deliver blistering, hardware-optimized performance for arrays of integers if those integers are just library structs? Lattner answers that "old tricks are the best tricks," pointing to the concept of zero-cost abstractions familiar from C++ and Rust. Mojo allows developers to stack abstractions like "turtles all the way down," but unlike traditional languages, Mojo changes what sits at the bottom of the turtle stack.

Recalling his work on Swift, Lattner jokes that he used to describe Swift as "syntactic sugar for LLVM" because types like `Int` were simply library wrappers around LLVM intermediate representation primitives like `i32` and `i64`. Mojo adopts that same architecture and amplifies it by a factor of ten using MLIR (Multi-Level Intermediate Representation). Because MLIR is a modern, modular compiler infrastructure, Mojo can expose low-level hardware concepts—such as `Float4`, exotic 4-bit and 8-bit numeric formats, and accelerator-specific operations like matrix multiplication on GPU Tensor Cores—directly to library code. Library authors can build rich syntactic sugar on top of exotic silicon without needing to modify the compiler itself.

As Lattner explains the structural shift: “Mojo does basically that same trick, but it supercharges it by moving to this MLIR world.”

- Abstractions collapse to zero overhead during compilation via MLIR. - Hardware-specific intrinsics (e.g., GPU Tensor Core tile matrix multiplies) are exposed as callable primitives rather than opaque compiler intrinsics. - Developers can extend the core language capabilities without needing to become compiler engineers.

---

[28:38](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1718s) Opt-In Hardware Acceleration and Cross-Architecture Code

Jenkins asks what this looks like in practice for a regular programmer—for instance, if someone wanted to write a complex number library in Mojo using Python-style syntax. Lattner explains that one starts simply by defining a struct containing two floats and overloading the `__add__` dunder method to implement operator `+`. However, if the developer wants peak performance, they can inspect the hardware target at compile time. Certain CPUs and accelerators feature single-instruction complex fused multiply-accumulate operations, replacing what would otherwise require four separate multiplications and two additions.

Using Mojo's compile-time metaprogramming system (acting like a modern, type-safe `#ifdef`), the library author can query machine capabilities: if the specialized hardware instruction exists, Mojo emits the direct MLIR hardware operation; otherwise, it falls back to the generic mathematical implementation. Crucially, the end-user consuming the library never has to worry about the underlying hardware specifics—they simply use the type, and it runs at maximum speed.

Lattner points out that Mojo was designed from scratch in 2022 rather than decades earlier, giving it native handling for modern computing realities like SIMD vectors and heterogeneous execution. A single Mojo source file can seamlessly target both a CPU and a GPU within the same program, handling differences in pointer sizes, numeric capabilities, and code generation behind the scenes. Jenkins marvels that this enables open-source contributors to submit performance-improving pull requests that plug in hardware-specific accelerators without altering user code or language syntax. Lattner agrees, enthusiastically sharing how community members have implemented algorithms like Conway's Game of Life and watched their code run a thousand times faster simply by leveraging Mojo's explicit SIMD primitives.

As Lattner summarizes the community's experience: “And so it’s been really fun seeing Mojo developers worldwide where they take something like, you know, Game of Life or whatever, and they just say, ‘Okay, I’ll start using this, I’ll try this. Oh, hey, wow, it’s 1,000 times faster than the code I started with.’ That’s cool, right?”

[31:42](https://www.youtube.com/watch?v=JRcXUuQYR90&t=1902s) Declarative Graphs and the ExaFLOP Supercomputer

Kris Jenkins asks Chris Lattner to connect the discussion to CPUs, GPUs, and the technical theories proven out in the MLIR ecosystem that make Mojo so compelling. Lattner explains that in the AI domain, he loves both user-facing applications and the underlying systems built to power them. Recalling his time working on the TPU project at Google, he marvels at the fact that any user can spin up a Jupyter Notebook on Google Cloud and, with just a few lines of code, program an exaFLOP supercomputer partitioned across thousands of accelerator chips.

```mermaid flowchart TD accTitle: Declarative AI Graph Compilation accDescr: Flow showing how declarative operations are fused and scheduled onto hardware clusters versus opaque C++ libraries.

subgraph UserLevel["User Specification"] A["Declarative AI Graph<br/>(Matmul, Conv, Gather, Reduce)"] end

subgraph CompilerStack["Max Engine & MLIR Stack"] B["Kernel Fusion & Loop Nest Optimizations"] C["Cluster Placement & Auto-Distribution"] end

subgraph Hardware["Execution Target"] D["Thousands of Accelerator Nodes<br/>(ExaFLOP Compute)"] end

A --> B B --> C C --> D ```

This leap was made possible by moving away from purely imperative code toward declarative programming. Instead of writing low-level message-passing (MPI) or imperative C++—which a compiler cannot easily parallelize across arbitrary nodes—AI researchers think in high-level parallel primitives reminiscent of APL, such as matrix multiplications, convolutions, gathers, and reductions. These operations form a computational graph that is handed off to an advanced compiler stack capable of fusing loop nests, optimizing math, and distributing tasks across clusters.

- Google Cloud Jupyter Notebooks give practitioners direct access to exaFLOP supercomputers containing thousands of accelerator nodes without requiring them to write manual HPC or MPI code. - Declarative specifications allow compiler systems to fuse loop nests and distribute identical tasks across machines, whereas attempting to automatically parallelize arbitrary imperative C++ is practically impossible. - Lattner compares the AI researcher's mental model to APL, where developers compose high-level, parallel array operations rather than micro-managing hardware execution.

[34:58](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2098s) The Max Engine, White-Box Kernels, and Replacing CUDA

Modular built the Max Engine to serve as an extensible AI compiler stack that incorporates the lessons learned from earlier frameworks like XLA. A central problem with existing AI infrastructure is that the ecosystem relies heavily on CUDA kernels or vendor math libraries like Intel MKL. Because those vendor operators are opaque black boxes, high-level graph compilers cannot see the logic inside them to perform deep compiler optimizations like fusion, scheduling, or placement.

```mermaid flowchart LR accTitle: Opaque versus Transparent Compiler Compilation accDescr: Comparison of traditional black-box CUDA math libraries against inspectable Mojo MLIR kernels.

subgraph Traditional["Traditional AI Stacks"] T1["Graph Compiler"] -.->|"Cannot inspect"| T2["Opaque CUDA / MKL Kernels<br/>(Black Box)"] end

subgraph MojoStack["Mojo & Max Engine"] M1["Max Engine Compiler"] -->|"Inspects via MLIR"| M2["Mojo Custom Operators<br/>(White Box Source)"] end ```

Mojo provides an alternative by allowing developers to write custom operators (such as a domain-specific FFT for signal processing) in straightforward syntax instead of alienating CUDA code. Because Mojo builds on MLIR, the Max Engine compiler can reflect directly into the implementation of custom kernels. It treats custom algorithms as transparent white boxes rather than opaque binaries, unlocking global fusion and cluster-wide optimizations while matching or beating vendor-tuned matrix multiplication performance.

> “And so instead of writing a CUDA kernel, you can write some Mojo code, and then the graph compiler and the other stuff can suck this up, because because of MLIR, we can now reflect onto it, and we can see what the code is doing.” — Chris Lattner

[37:22](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2242s) Healing the Production Divide Between Research and Deployment

Kris notes the steep divide between defining a data graph and implementing the low-level custom nodes within it. Lattner explains that the structural rift in machine learning is even wider due to how the field evolved. Frameworks like TensorFlow and PyTorch were designed 8 to 10 years earlier for research labs and model training. However, the modern AI industry has overwhelmingly shifted toward deployment, where running Python in production services introduces severe performance and packaging headaches.

```mermaid flowchart TD accTitle: The Two-Language Problem in AI Production accDescr: How Mojo bridges the divide between Python AI researchers and C++/Rust systems deployment engineers.

subgraph LegacyDivide["The Fragmented Workflow"] R["AI Researchers<br/>(Python / PyTorch)"] -->|"Throws over the wall"| D["Deployment Engineers<br/>(Rewriting in C++ / Rust)"] end

subgraph UnifiedMojo["The Mojo Solution"] M["Mojo Unified Language<br/>(High-level Python ergonomics + Bare-metal performance)"] end

LegacyDivide -.->|"Replaced by"| UnifiedMojo ```

As a consequence, production teams are frequently forced to rewrite models and auxiliary pipeline components—such as LLM tokenization logic—into C++ or Rust so they can actually be shipped. This dynamic splits organizations into isolated camps that literally speak different programming languages, creating friction and throttling deployment velocity. Mojo is designed to heal this rift by providing a single scalable language that satisfies AI researchers, systems engineers, and numeric programmers alike.

- Frameworks like TensorFlow and PyTorch were architected roughly 8 to 10 years ago with a heavy focus on research and model training rather than production efficiency. - Modern production environments often require completely reimplementing pipelines, preprocessing, and LLM tokenizers in C++ or Rust to bypass Python runtime constraints. - Lattner acknowledges that creating a brand-new programming language is a multi-year bet that sounds insane to many, but argues it is necessary because rapid, piecemeal "hill-climbing" over the last eight years prevented the industry from redesigning its tools from first principles.

> “And so a big part of what Mojo is actually about is by solving that problem by having one language that can scale, we can heal this divide between all the personas that are building these systems, whether they're high performance, numeric people, whether they're deployment engineers, whether they're AI researchers, and get just get everybody to be able to talk to each other...” — Chris Lattner

[40:35](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2435s) Writing High-Performance Kernels: Dispelling the "Never Write a For Loop" Rule

When Kris asks what it actually feels like to write an operator inside this graph using Mojo, Lattner describes it as writing C++ or Rust algorithms wrapped in clean Python syntax—stripping away verbose template metaprogramming and line noise. Instead of relying on raw, low-level looping patterns, developers frequently compose higher-order functions and library combinators, such as passing execution closures into built-in `parallelize` and `vectorize` functions.

Crucially, writing Mojo shatters standard Python performance intuitions. Traditional Python developers are drilled never to write nested `for` loops because the standard CPython interpreter incurs crippling overhead, driving users toward pre-compiled C extensions instead. Because Mojo shares none of Python’s underlying implementation or runtime DNA, that dogma no longer applies: writing explicit loops is completely fine and executes at bare-metal speeds, even when targeting low-level primitives like hardware Tensor Cores.

> “And so in Mojo, all that wisdom is invalid, because it has none of the DNA of Python.” — Chris Lattner

[42:09](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2529s) Assembly in Python Syntax and the Pragmatism of Mojo

Chris Lattner describes the reaction of engineers working deep in hardware architectures—such as AVX-512 and VNNI—when they first encounter Mojo: “And they're like, it's so weird to be writing assembly code in Python.” While writing machine-level code inside Python syntax initially disorients developers or shifts their perspective, the familiar syntax makes the code accessible. Lattner emphasizes that Mojo is not designed around innovation simply for the sake of novelty: “And again, it's not a lot of what we're going for isn't driven by novelty, for novelty's sake, it's about pragmatism.”

[42:38](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2558s) Compile-Time Metaprogramming: Beyond C++ Templates and Zig

Turning to metaprogramming, Lattner explains that AI model definitions in Python are already de facto metaprograms—imperative code executing to build a compute graph that is subsequently distributed, transformed, and optimized. In high-performance numerics, developers historically turned to C++ templates to write generic algorithms supporting both `float32` and `float64`, but that practice frequently devolved into a complex, hard-to-maintain templating mess. Newer systems languages like Zig addressed this by eliminating distinct meta-languages and running the core language at compile time.

Mojo adopts and extends this concept. Because dynamic Python features carry runtime overhead that bare-metal performance cannot tolerate, Mojo fuses Python's dynamic ergonomics with compile-time metaprogramming (`comptime`). Developers can run standard algorithms, allocate dynamic heap data structures, and invoke functions during compilation without expending a single CPU clock cycle at runtime.

```mermaid flowchart LR accTitle: Compile-Time Execution to Static Binary accDescr: Functions run with static inputs at compile time to produce embedded static objects in the binary. subgraph CompileTime["Compile-Time Execution"] A["Static Inputs"] --> B["Normal Mojo Function"] B --> C["Heap Allocation / Dynamic Logic"] end subgraph Output["Binary Generation"] C --> D["Result Object (e.g., List)"] D --> E["Baked into Executable"] end ```

When Kris Jenkins asks if Mojo allows writing Python at compile time to generate an abstract syntax tree (AST), Lattner clarifies that while AST manipulation is theoretically possible in the future, Mojo's current design focuses on executing standard functions over static inputs:

* A lookup table function can run dynamically with static parameters during compilation, construct a collection (like a list or `std::vector`), and embed the final result directly into the executable as a precomputed object. * Types are treated directly as compile-time values, allowing library authors to build expressive higher-level combinators and domain-specific abstractions. * In response to Jenkins referencing Lisp and Zig's low-level minimalism, Lattner remarks that developers routinely cycle back to fundamental concepts: “Everybody's doomed to re implement their own list, right?”

[48:22](https://www.youtube.com/watch?v=JRcXUuQYR90&t=2902s) Memory Management: CPython Compatibility and Native References

Kris Jenkins notes that low-level hardware control inevitably raises the question of memory management. Lattner explains that Mojo supports two distinct paradigms depending on whether code interacts with standard Python or runs natively:

1. **CPython Compatibility:** When interoperating with standard Python, Mojo maintains the CPython object model using traditional boxed objects with reference counting. 2. **Native Mojo Systems Layer:** Native code introduces types equipped with explicit move constructors, copy constructors, and destructors, along with unsafe hooks to call low-level C functions like `malloc` and `free`.

To combine safety with performance, Mojo implements a reference and borrowing system conceptually modeled after Rust, but adapted to be significantly less obtrusive: “In mojo, it's way less in your face, and you don't have to micromanage the borrower checker quite as much, but it provides you the same approach and the ability to manage references.”

[50:55](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3055s) ASAP Destruction vs. Lexical Scope Lifetimes

Lattner contrasts Mojo's borrow checker design directly with Rust's approach. In Rust, values are tied to lexical scope and destroyed at the end of the enclosing block, which often leads to borrow checker exclusivity conflicts and necessitates mechanisms such as non-lexical lifetimes or runtime drop flags.

In Mojo, the borrow checker does not act purely as an enforcer over parser-generated intermediate representation; instead, it proactively computes the exact lifetime of values:

* **Eager Destruction:** Mojo destroys a value immediately after its final use, behaving like an exceptionally fine-grained, instantaneous resource cleanup mechanism. * **Reduced Exclusivity Collisions:** Because values drop early rather than waiting for scope boundaries, mutable borrow constraints are relaxed faster, sparing developers from wrestling with the borrow checker. * **Resource Optimization:** Releasing memory early is critical in AI workloads where a single GPU tensor might consume four gigabytes of VRAM. * **Tail Call Preservation:** Traditional lexical destructors execute after a function's final statement, preventing true tail call elimination; Mojo's immediate cleanup model avoids this stack conflict.

[52:41](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3161s) Compile-Time Lifetimes and Zero-Copy Moves

Chris Lattner explains that Mojo completely defines away a thorny problem present in both Rust and Swift: determining whether a stack slot is live or dead. In languages like Rust and Swift, assignment (`=`) can signify either an in-place reassignment/mutation over an existing value or the initial initialization of a slot. Because Rust allows values to be moved out of a slot, tracking stack liveness becomes intricate. When Kris Jenkins asks whether Mojo's approach relies on runtime reference counting, Chris clarifies that this tracking happens entirely at compile time via lifetimes.

Chris reflects on his long history working alongside figures like Graydon Hoare and the broader Rust community, pointing out that Rust has been built on LLVM from the beginning. While expressing immense respect for Rust, he emphasizes that it is now roughly 14 years old—about the same age as Swift. Mojo capitalizes on a decade and a half of lessons learned from both ecosystems to simplify language ergonomics and performance.

One major architectural benefit of Mojo's design is native support for `async`/`await` without requiring Rust-style "pinning." Because all values have concrete identity in Mojo, the language circumvents the hidden overhead typical of systems programming languages. Rust programs often emit frequent memory copies (`memcpy`) under the hood when moving values, relying on compiler optimizations that may or may not succeed in eliminating them. In Mojo, the system composes cleanly so that implicit memory copies caused by moves simply never occur.

- Rust and Swift treat `=` ambiguously as either value mutation or first-time initialization depending on the context of stack slot liveness. - Mojo tracks variable ownership and lifetimes purely at compile time, eliminating runtime reference counting overhead. - In Mojo, native async operations avoid pinning requirements because all values carry identity by default. - Unlike Rust, where move operations can generate implicit memory copies when optimization passes fail, Mojo guarantees zero implicit `memcpy` calls during moves.

> “And so what Mojo represents is an opportunity to take the learning and do something that's the next step.” — Chris Lattner

---

[55:19](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3319s) Bridging Functional Purity and In-Place Mutation

Kris wonders whether Mojo's concept of value identity impacts immutable data structures. Chris looks back on his work on Swift—started around 2010—which incorporated functional programming idioms while addressing performance concerns. He jokingly anticipates a "bar fight" between functional purists and C++ practitioners: pure functional developers prize immutability because generating new values ensures composition and eliminates "spooky action at a distance," whereas C++ engineers object that allocating a brand-new list for every single insertion is catastrophic for hardware performance.

Swift resolved this debate through exclusive ownership and value semantics, an approach Mojo builds upon. If the runtime system guarantees that code has exclusive access to a value, it can mutate that value directly in place while presenting an immutable interface to the rest of the application. In Swift, fundamental types such as strings, arrays, and dictionaries behave like immutable values from the developer's perspective (similar to Java's model), yet avoid hidden deep copies underneath. Mojo adopts this philosophy to marry the predictability of functional programming with the raw speed of in-place mutation, while correcting Swift's historical missteps around excessive implicit copying.

```mermaid flowchart TD accTitle: Value Semantics with In-Place Mutation accDescr: Flowchart illustrating how exclusive ownership enables in-place mutation while preserving functional predictability without deep copies.

subgraph OwnershipCheck["Safety & Concurrency Guarantee"] A["Caller passes data"] --> B{"Exclusive Ownership?"} end

subgraph MutationExecution["Memory Execution"] B -- "Yes (Single Reference)" --> C["In-Place Local Mutation<br/>(C++ Level Efficiency)"] B -- "No (Shared References)" --> D["Defensive Copy / Isolation<br/>(Functional Predictability)"] end

C --> E["Preserves External Immutability"] D --> E ```

When Kris questions whether managing exclusive access might burden Python programmers with unfamiliar complexities, Chris emphasizes that the entire ownership system is strictly opt-in. Programmers can write fully dynamic, standard Pythonic code whenever they choose. Chris observes that modern Python is practically "only half the language"—developers write Python scripts for orchestration, but inevitably drop down into C, C++, or Rust when scale or performance demands it. Mojo aims to unify both sides under a single syntax, allowing developers to write high-performance low-level routines with dunder methods like `__add__` directly in Mojo instead of juggling foreign function interfaces (FFI) and external bindings.

- Swift introduced value semantics to bridge functional predictability and hardware-level performance by permitting local mutation on exclusively owned data. - Standard Swift data types (Array, String, Dictionary) enforce value semantics, preventing external modification without invoking deep copies. - Mojo's ownership model is entirely opt-in; dynamic Python features remain untouched for high-level scripting. - Rather than replacing Python's syntax, Mojo replaces the underlying C/C++ extension layer, eliminating foreign function interface (FFI) glue code.

> “One way to look at modern Python is that Python is only half the language. You have Python and then you have C.” — Chris Lattner

---

[01:00:03](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3603s) Parallelism, Hardware Scaling, and Future Actor Models

The discussion moves to concurrency and parallelization. Kris brings up Python's infamous Global Interpreter Lock (GIL) and asks how Mojo prevents the hazards of multithreading without sacrificing ergonomics. Chris confirms that parallelism is a first-class priority in Mojo, designed specifically for modern compute hardware where single servers can easily house 256 physical CPU cores—a scale bound to expand in coming years.

Instead of hard-coding heavy concurrency structures directly into the compiler, Mojo provides high-performance parallel execution through core library primitives. Developers can take an existing function and drop it into a built-in `parallel_for` loop backed by an optimized low-level threading engine.

Addressing language-level coordination, Kris asks whether Mojo plans to adopt an actor model. Chris notes that while Swift implemented a type-safe distributed actor runtime on top of `async`/`await`, the Modular team has not yet built an actor system for Mojo. Instead, current development focuses squarely on structured compute, numerical workloads, and supercomputing-style tasks. He suggests an actor framework could begin its life as a user-level library—drawing parallels to Akka in the Scala ecosystem—before evaluating whether specialized compiler support and type-system hooks are needed to guarantee memory-safe actor boundaries.

- Mojo natively targets high-core-count hardware topologies (e.g., modern 256-core server CPUs) rather than classic 4-core or 8-core desktop limits. - Parallel processing is provided out-of-the-box using library abstractions, including high-throughput `parallel_for` routines. - Swift previously built a full distributed, type-safe actor system directly on top of `async`/`await`. - Mojo's roadmap prioritizes numerical and structured workloads first, leaving room for future community-driven or library-level actor implementations.

> “Right now we're very focused on the structured compute, more supercomputer style, and the numeric side of things.” — Chris Lattner

[01:02:59](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3779s) Hardware Abstractions, Heterogeneity, and Memory Hierarchies

While developers can still drop down into arbitrary C code and do whatever they want, Mojo aims to raise the abstraction level so they do not have to live in the low-level muck. Even an imperative construct like a parallel for loop feels significantly more declarative when users can simply instruct the compiler to execute a block in parallel. Kris Jenkins raises the critical problem of hardware variance: scheduling threads across a single core behaves completely differently than managing a 256-core machine, prompting the question of how much hardware architecture leaks into Mojo and how much direct control programmers have. Chris Lattner separates this into two distinct concerns: how much a developer is *forced* to care about, versus how much they are *permitted* to care about if they choose to optimize.

```mermaid flowchart TD accTitle: Hardware Memory Hierarchy from Registers to RAM accDescr: A pyramid showing the multi-tier memory hierarchy found in modern CPUs and GPUs, moving from fast register files to slower main memory.

subgraph MemoryHierarchy["Memory Hierarchy (CPU & GPU)"] L0["L0 / Register File<br>(Vector registers, immediate access)"] L1["L1 Cache<br>(Very fast, core-adjacent)"] L2["L2 Cache<br>(Shared across 1-2 cores)"] L3["L3 Cache<br>(Shared across all cores)"] RAM["Main Memory<br>(High capacity, high latency)"]

L0 --> L1 L1 --> L2 L2 --> L3 L3 --> RAM end ```

Most developers just want to supply a parallel loop and let the runtime handle the details. At the systems level, Mojo supports structured, nested parallelism alongside composable threading libraries and async/await mechanisms to prevent thread proliferation—spawning tens or hundreds of thousands of raw OS threads that would otherwise overwhelm the operating system. The real complexity begins when moving from 256-core CPUs to GPUs hosting thousands of simultaneous cores and threads under a radically different programming model.

While high-level declarative compute graphs can be ported across hardware targets relatively cleanly by swapping out backend implementations, low-level imperative loops do not port as easily. At this imperative bottom layer, hardware accelerators introduce a massive challenge: memory access patterns. “When you start talking about accelerators, really what ends up mattering a lot is both parallelism, but then also memory,” Lattner explains. “And so how you use the memory hierarchy is the most important thing these days, particularly for GPUs and LLMs in this world that we inhabit.” Modern hardware relies on deep memory tiers: - Vector register files serving as an ultra-fast L0 cache. - Core-adjacent, high-speed L1 cache. - L2 cache, often shared between one or two cores. - A broad L3 cache shared across all processor cores. - High-capacity, higher-latency main memory.

---

[01:07:31](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4051s) Tensors, Striding, and Tile-Based Programming

To illustrate why memory hierarchy dictates performance, Lattner walks through how multidimensional data structures actually exist in physical hardware. In computer graphics, a texture is a two-dimensional rectangle of data; artificial intelligence generalizes this into an $n$-dimensional tensor. Regardless of dimension, hardware linearizes arrays into a continuous, flat sequence of memory addresses.

Moving horizontally across a row simply increments a pointer to the next adjacent address, which is optimal for hardware prefetchers and cache locality. Moving vertically down a column, however, forces the pointer to stride forward by an entire row's length in bytes. In high-dimensional tensors, this striding causes significant performance degradation because cache lines cannot be read sequentially.

```mermaid flowchart LR accTitle: Matrix Tiling and Memory Access accDescr: Illustration comparing continuous row traversal against strided column traversal and how 2D tiles solve locality issues.

subgraph MemoryLayout["Linearized Memory"] direction TB RowAccess["Row Traversal: Ptr + 1<br>(Fast, contiguous cache access)"] ColAccess["Column Traversal: Ptr + Row Length<br>(Slow, strided memory jumps)"] end

subgraph TilingStrategy["Tile-Based Processing"] direction TB TileBlock["2D Tile (e.g., 4x4, 16x16, 128x128)"] Orchestration["Higher-Order Combinators<br>(Prefetching, transposing, cache reuse)"] TileBlock --> Orchestration end

MemoryLayout --> TilingStrategy ```

In operations like matrix multiplication, a naive calculation computes dot products by reading the row of one matrix and the column of another, immediately colliding with striding penalties. Developers can combat this by transposing matrices ahead of time or reading blocks of multiple rows and columns together. This strategy naturally scales into tile-based programming models, where computations operate over discrete multi-dimensional blocks (tiles) of data rather than individual scalar loads, stores, adds, and multiplies. Silicon designers have leaned into this architectural reality by baking physical matrix multiplication units directly onto the die: - Accelerators frequently execute small matrix multiplications natively (such as $4 \times 4$ or $16 \times 16$ blocks). - Specialized chips scale this hardware support up to native $128 \times 128$ matrix primitives. - The physics of chip design favors this layout: “The intuition here is that AI is important to the world and silicon is fundamentally two dimensional,” notes Lattner. “And so if you use the two dimensional nature of silicon to put down a matrix multiplication, you can get a lot of performance and energy and other benefits from that.”

---

[01:11:03](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4263s) Unifying Tile Algorithms, Combinators, and Future-Proof Software

High-performance computing (HPC) has wrestled with hardware mapping and memory hierarchy for decades. Historically, communities turned to Fortran libraries or complex C++ template metaprogramming. While those solutions delivered raw performance, they remained niche, rigid, and notorious for poor usability and steep learning curves.

Mojo bridges this gap by decoupling the core numerical calculation from the platform-specific execution schedule. Programmers write the mathematical algorithm for an individual tile, while higher-order combinators handle orchestration logic—such as hardware prefetching two steps ahead, deciding vertical versus horizontal traversal orders, or reordering memory layouts to maximize cache reuse. Through compile-time metaprogramming, these modular tile operations combine to produce portable, native machine code for both CPUs and GPUs without sacrificing device-specific features.

Lattner recounts sharing these techniques during a technical talk at NVIDIA's GTC conference, demonstrating how the exact same high-performance Mojo numeric algorithms run across both CPU and GPU targets. Writing portable, performant code is not merely about surviving today's hardware fragmentation; it preserves long-term software investments across decades of rapid silicon evolution: - “It's not just about today thing of software, a GPU and CPU,” Lattner emphasizes. “It's about if you're making a major investment in building software, and that's how software works, like you want your software investment to last for 10 years or 20 years, you want the amount, a certain amount of being able to adapt to the needs of new hardware.” - In an era where silicon advances faster than ever, Mojo aims to eliminate the historical compromises between clean algorithmic code, portability, and low-level hardware utilization.

[01:13:00](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4380s) Hardware Access via MLIR/LLVM and the MAX Engine

When new CPU instructions or accelerator capabilities are released, Mojo does not require programmers to invent low-level bindings from scratch. Chris Lattner highlights NVIDIA as a prime example of a good ecosystem citizen: whenever they release a new chip, they generally provide LLVM access right away, allowing developers to plug straight into that stack. Modern hardware vendors are overwhelmingly LLVM-friendly, and because Mojo directly speaks to MLIR and LLVM, it inherits direct access to emerging hardware features immediately.

```mermaid flowchart TD accTitle: Mojo Hardware and Engine Architecture accDescr: Flow diagram showing user entry points down to hardware execution through LLVM and MLIR.

subgraph HighLevel["High-Level Abstractions"] direction LR ME["MAX Engine<br>(Graph-level execution)"] PY["Typed Python / Mojo Code<br>(100x–1000x CPU speedup)"] end

subgraph Compiler["Compiler Infrastructure"] direction LR MJ["Mojo Compiler"] MLIR["MLIR Pipeline"] LLVM["LLVM Backend"] end

subgraph Hardware["Target Hardware"] direction LR CPU["CPUs"] GPU["GPUs / Accelerators<br>(NVIDIA, etc.)"] end

HighLevel --> MJ MJ --> MLIR MLIR --> LLVM LLVM --> Hardware ```

Zooming back out, Lattner acknowledges that manipulating direct machine instructions is “deep nervery” that matters deeply to a small group of engineers, but the vast majority of developers simply want higher-level abstractions. For users who do not want to understand the underlying mechanics, Modular offers the MAX Engine, where users can simply hand over a compute graph without caring how it executes underneath. For others, simply taking existing slow Python code, putting in type annotations, and compiling it with Mojo yields a 100x to 1,000x performance increase on standard CPUs without touching accelerator hardware or retraining engineering teams.

- NVIDIA typically provides LLVM access as soon as new hardware becomes available, giving Mojo a direct path to new chips. - Hardware makers across the industry are increasingly standardizing around LLVM, accelerating hardware-software co-design. - Developers with massive investments in Python code can achieve 100x–1000x CPU speedups simply by adding types in Mojo, avoiding the need to rewrite everything in C++ or Rust.

[01:14:45](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4485s) Meeting Programmers Where They Are: Lessons from Swift

Kris Jenkins notes that from his perspective, he has no desire to write GPU-level code—he just wants his programs to be fast, and when performance drops, he does not want to be told he chose the wrong language. Lattner explains that this fundamental dilemma informed the decision to build Mojo around Python syntax. Making a broad generalization about software engineers, Lattner points out that developers are overwhelmingly busy. While researchers and enthusiasts love learning tools purely for the sake of it, practical working engineers rarely have the bandwidth to set aside a week or a month to master an entirely alien ecosystem.

If an ecosystem meets developers where they are by providing familiar syntax and mental models, engineers do not have to retrain from scratch. Once comfortable, they genuinely enjoy leveling up. Lattner recalls seeing this exact dynamic during the rollout of Swift: > “We said to the Objective-C world, hey, you're all familiar with classes, classes are great, they still work in Swift. Here's a new thing called a struct. It's got these different tradeoffs, it's way more efficient, it doesn't use dynamic dispatch or whatever.”

Introducing structs alongside algebraic data types (enums with payloads) and pattern matching triggered major "aha moments" for developers who were able to grow incrementally from an established baseline. Mojo applies the same philosophy to the Python community, avoiding the demand that developers abandon their knowledge base to attend an intensive boot camp before becoming effective.

[01:17:04](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4624s) Mojo’s Maturity, Open Sourcing the Standard Library, and Community

Assessing Mojo’s real-world status, Lattner notes that the language remains young, having launched publicly in May 2023 (less than a year prior to the recording). Despite its youth, adoption has expanded rapidly: - Over 175,000 developers have used Mojo. - More than 22,000 members belong to the official Discord community, where members jokingly refer to themselves as “magicians.” - In an intentional bit of fun, Mojo supports a literal fire emoji (`🔥`) file extension alongside standard `.mojo` files.

Crucially, on the day of the recording, Modular announced the open-sourcing of Mojo’s entire standard library under the Apache 2.0 license (with patent protection clauses). Having built open source communities like LLVM from university research and led Swift’s open source rollout, Lattner emphasizes that open source requires far more than tossing code onto GitHub; it requires clear contribution guidelines, inclusive collaboration, and legal best practices. While the language was engineered to solve brutal architecture and systems bottlenecks in AI, it is completely general-purpose, and the community is already building tools in domains like web development where Modular itself does not have the capacity to invest directly.

[01:20:18](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4818s) Python Compatibility Today: Interop vs. Native Classes

For developers seeking to build projects like web servers in Mojo today, Python interoperability is already seamless. A developer can import existing Python packages directly into Mojo without authoring manual C wrappers or bindings—it will execute out of the box.

However, translating raw Python code into a native `.mojo` source file currently reveals significant feature gaps: - **Classes are currently missing**: Native Python-style dynamic classes are not yet implemented in Mojo, representing the single largest missing language feature for typical Python programmers. - **Systems features are robust**: Structs, value ownership semantics, references, and static compile-time mechanisms—analogous to C++ and Rust—are fully functional. - **Roadmap timeline**: Systems programmers will feel at home immediately, while pure Python programmers will find the language far more comfortable in roughly six months once classes land.

Lattner reflects on how developers still approach him on the street to thank him for Swift, saying it gave them the courage to learn programming when Objective-C felt terrifying. He holds the same long-term ambition for Mojo: removing the artificial barrier between "Python scripting" and "real systems coding." > “And so with Mojo, what I hope happens, and these things take a couple of years to play out, but what I hope happens is we get all these people that know Python and they don't consider themselves to be real coders or something, but they know Python and they can continue to grow, right?”

By eliminating the rigid threshold between high-level Pythonistas and low-level C++ or Rust engineers, the broader programming ecosystem can become far more inclusive to inventive ideas. Lattner wraps up the segment by expressing his genuine enthusiasm for developer tools and sharing his appreciation for the *Developer Voices* show, prompting Jenkins to joke that he did not pay Lattner for the endorsement.

[01:22:52](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4972s) Unifying Programming and Validating Python Developers

Kris Jenkins wraps up the discussion by championing anything that introduces fresh concepts to developers and works toward healing the fractured software landscape, noting: “anything that brings new ideas to programmers and helps unify our somewhat fragmented view of programming, I'm all for it.” Chris Lattner shares the sentiment, expressing his gratitude for being invited onto the show as the interview draws to a friendly close.

Picking up on an emotional thread from their conversation, Kris takes a moment to speak directly to Python developers who might harbor imposter syndrome or feel marginalized by traditional systems programmers. He voices genuine sadness at the notion that anyone writing Python might feel they do not count as authentic software engineers. Refuting that gatekeeping mindset entirely, Kris insists: “If you were in the business of teaching computers to do things they couldn't do before, you're a real programmer. Don't let anyone tell you different.” He extends an open hand to anyone driven to improve their craft and investigate emerging paradigms, calling them kindred spirits.

In his final sign-off, Kris encourages listeners to consult the show notes to explore Mojo firsthand and test out its capabilities. Sharing his own impressions, he notes that while it is still early days, the language feels exceptionally promising and fun to experiment with. He closes by asking the audience to like, share, rate, and subscribe to help support the channel and guide like-minded developers toward the conversation, formally concluding the *Developer Voices* episode with Chris Lattner.

## Notable quotes > [55:19](https://www.youtube.com/watch?v=JRcXUuQYR90&t=3319s) One way to look at modern Python is that Python is only half the language. You have Python and then you have C. — Chris Lattner

> [01:22:52](https://www.youtube.com/watch?v=JRcXUuQYR90&t=4972s) If you were in the business of teaching computers to do things they couldn't do before, you're a real programmer. Don't let anyone tell you different. — Kris Jenkins

> [01:51](https://www.youtube.com/watch?v=JRcXUuQYR90&t=111s) C++ is a very interesting, informative language, very challenging technical problem to implement. And at least for me, I could not survive that experience without thinking maybe there could be something new and better. — Chris Lattner

## Mentioned Akka, APL, AVX-512, Bjarne Stroustrup, C++, Chris Lattner, Clang, CPython, CUDA, Developer Voices, GHC, Google, Graydon Hoare, Haskell, Intel MKL, Kris Jenkins, Lisp, LLVM, Max Engine, MLIR, Modular, Mojo, NVIDIA, NumPy, Objective-C, PlayStation 5, PureScript, PyTorch, Python, Rust, Scala, Swift, TensorFlow, TPU, TypeScript, VNNI, XLA, Zig

## Video description Mojo is the latest language from the creator of Swift and LLVM. It’s an attempt to take some of the best techniques from CPU/GPU-level programming and package them up in a Python-compatible syntax.

In this episode we explore why the Mojo programming language was created, and what it offers to Python programmers and non-Python programmers alike. How is it built for performance, and which performance features matter? What’s its take on functional programming and type systems? And can it marry the high-level programming of Python with the low-level programming of LLVM/MLIR?

If you’re a Python programmer who needs better performance, a C programmer who expects more from a ‘scripting language’, or just someone who’d be happier if Python had a first-class type system, Mojo might well be for you…

–

Mojo: https://www.modular.com/max/mojo Mojo’s Roadmap: https://docs.modular.com/mojo/roadmap.html The Mojo Discord: https://discord.com/invite/modular MLIR: https://mlir.llvm.org/ Chris’s Talks: https://nondot.org/sabre/Resume.html#talks

Chris on Twitter: https://twitter.com/clattner_llvm Kris on Mastodon: http://mastodon.social/@krisajenkins Kris on LinkedIn: https://www.linkedin.com/in/krisjenkins/ Kris on Twitter: https://twitter.com/krisajenkins

–

#software #podcast #mojolang #ml #pythonml

[Source](https://www.youtube.com/watch?v=JRcXUuQYR90)

中文简报

Lattner打造Mojo以消除AI芯片上的Python C语言瓶颈 Mojo通过将Python语法直接与MLIR原语相结合,消除了计算领域的双语言鸿沟,使开发者无需使用C++或CUDA重写关键内核即可面向专用硬件编程。 Modular创建Mojo旨在化解现代硬件危机,并通过将高级动态语法与裸机系统性能相结合,消除Python长久以来的“双语言问题”。Mojo并非将Python包装在另一个嵌入式DSL中,而是完全基于MLIR从零构建,直接生成中间表示以暴露硬件原语、SIMD指令和张量加速器。它引入了可靠的未装箱机器类型、编译期元编程(comptime)、急切析构,以及一种改进了Rust和Swift所有权模型的可选借用检查器。通过在提供零成本系统抽象的同时实现无缝的双向Python互操作,Mojo让开发者能够从快速原型设计平滑过渡到高性能AI部署及系统编程。 Mojo通过围绕MLIR从根本上重新设计编译器架构,在解析过程中直接生成中间表示以面向CPU、GPU和专用AI加速器,从而化解了Python的性能瓶颈。 (3:44) 通过采用Python语法,Mojo消除了机器学习中经典的“双语言问题”,允许开发者在无需转入C、C++或Fortran扩展的情况下编写原生系统代码和裸机循环。 (17:15) Mojo利用急切析构和可选借用检查重新设计了内存管理,在变量最后一次使用后立即自动释放内存,以优化大型张量工作负载并保留尾调用消除。 (50:55) Modular在包含专利许可的Apache 2.0协议下开源了Mojo的标准库,开发者规模迅速扩大至超过175,000人,并实现了与现有CPython库的直接互操作。 (77:04)

Source quotes

[55:19] Chris Lattner: One way to look at modern Python is that Python is only half the language. You have Python and then you have C. [82:52] Kris Jenkins: If you were in the business of teaching computers to do things they couldn't do before, you're a real programmer. Don't let anyone tell you different. [1:51] Chris Lattner: C++ is a very interesting, informative language, very challenging technical problem to implement. And at least for me, I could not survive that experience without thinking maybe there could be something new and better.

Original transcript

[0:00] Could Python become a high-performance parallel programming [0:03] language? That seems unlikely. I mean, there are some fundamental [0:07] architectural reasons why that feels like a bigger shift than [0:11] Python 2 to Python 3, and that was a big enough shift already. But I [0:16] raised the question so that I can flip it on its head. Could a [0:20] high-performance parallel programming language become Python? [0:25] That to me seems more reasonable. Start with a low-level, [0:29] compiler-level language. Do your performance work. Figure out those parts. [0:34] And then when you build up into user space and choose a [0:37] syntax, why not Python? Now that broadly is the approach taken [0:43] by the new language Mojo and its creator, Chris Latner. If you've [0:47] not heard of Chris, I'm certain you've heard of his work. [0:50] He created LLVM. He created Clang, the other big C C++ compiler. He created [0:56] Swift, the language of shiny Apple products everywhere. He has [1:00] serious form in language design, and he's one of the few [1:03] people I know that actually could run the gauntlet from Python syntax [1:08] all the way down to CPU and GPU and back. And he has some really [1:13] interesting ideas for his latest language, like "Let's do Python [1:17] but bring in a gradual type system. Let's make parallelization a [1:22] first-class concern. Let's give the programmer direct access to compiler [1:26] instructions. Lots of interesting new toys, [1:30] in familiar clothing." So I suggest we go and take a look at it. I'm [1:34] your host, Kris Jenkins. This is Developer Voices, and today's [1:37] voice is Chris Latner. [MUSIC] [1:51] Joining me today is Chris Latner. Chris, how are you? [1:54] I'm doing great. Thank you for having me, Chris. [1:57] Absolute pleasure. It's not often I get a guest with quite the CV, [2:02] quite the resume, as you say, that you have. You've got a heck of a [2:07] backstory which we could talk about in itself, [2:09] but we always talk about the future on this podcast. So let me get this [2:12] straight. You've been a founding part of LL... Yeah, that was [2:18] my master's research project. That's a good start. You didn't rest in [2:22] your laurels. You went on to Clang and Swift. [2:25] Yeah. Also, nights and weekends problem. Yeah, nights and weekends [2:30] project for a year and a half, and then it kind of grew a little bit [2:32] beyond that. Was that how it got started? Yeah, yeah. So I mean, I'm the kind of [2:36] person that I'm working on the thing I'm supposed to be [2:39] working during the day, but also pushing [2:40] boundaries during the evenings. And so in the case of Swift, we were wrapping up [2:45] the Clang C and C++ compiler. And C++ is a very [2:49] interesting, informative language, very challenging technical problem to [2:53] implement. And at least for me, I could not survive that experience [2:56] without thinking maybe there could be something new and [2:58] better. And so this is where Swift started bubbling in the [3:01] background and eventually got to the point where I could understand what [3:05] it was that I was building and working on and then shared [3:08] with some other people. I always feel like Swift was the language [3:13] that saved people that weren't me. I spent a good number of years [3:17] writing Objective C, kind of drowned and got off that boat, [3:21] and then Swift came along just as it would have saved me. Yeah, [3:25] Swift is a great language. It was a lot of fun. I learned a lot from [3:27] that. So this is the thing. So with a background like yours, [3:32] there's almost no point asking you why you're writing a new [3:36] language, because it seems almost inevitable that you would write a new [3:41] language. And what we have to talk about is why this one. [3:44] Yeah, maybe you could flip around and say, "Given you know how hard it is, [3:48] how can you be insane enough to do this again?" [3:51] Well, you were glutton for punishment. Yeah, well, I mean, I'm not afraid of [3:55] hard things, I guess. I think that is true. But [3:57] really, it was... I mean, you've talked with many folks that have [4:00] built languages and are working on it, and everybody has different [4:02] motivations. For me, it really comes down to solving a problem. [4:07] And so I actually resisted building a language, so in this case, Mojo. Because [4:13] having gone through, for example, the Swift experience, before [4:17] that I also built OpenCL, which is a GPU programming [4:20] thing many years ago. When you start from that, let's go solve [4:26] the programmer's problem, typically start from syntax. In the case [4:31] of Swift, started with, "Okay, I want auto closures, [4:33] and I want these higher order functional programming things, and I want to be able [4:36] to compose that in into the LVM compilation flow and all [4:40] these kinds of things." And very much started from syntax. In the [4:44] case of Mojo, at Modular, we started with a, [4:46] "How do we make GPUs go burr?" How do we make these crazy [4:52] high-performance CPUs that have matrix operations and Bfloat16 and other [4:56] AI extensions, how do we rationalize this wide [5:00] array of different hardware and put it into a system that we can [5:03] program it? And what's changed in hardware is that it used to be that a [5:09] CPU would come out every year, and it would be slightly [5:11] better than the old one, and everything would just magically go [5:13] faster. A compiler might do a different instruction scheduling or [5:18] certain code generation tricks. But generally, if you [5:21] recompile your code, old code ran faster. But today, what's happening [5:25] is we get all these really weird, dedicated hardware blocks. These [5:29] are very specialized. I mean, the most extreme is a GPU. [5:33] And so being able to program these things requires fundamentally [5:36] different kinds of software. And so what we started on at Modular is [5:40] not building a language. Actually, what we started [5:41] building is a very fancy code generator that had no front end. And [5:47] so we just built pure compiler codegen stuff, like replacing big chunks [5:51] of LLVM, replacing and building new ways of synthesizing [5:55] high-performance loop nests and things like this. And then just [5:59] wrote everything in IR directly. And so we were using, in this case, built [6:05] a new compiler framework called MLIR. It's now part of [6:08] the LLVM family, but it's a next generation replacement for [6:11] LLVM in many ways. And so that allows you to just write IR. And so we [6:16] did that for quite some months to just prove out that the [6:19] code generation philosophy in the stack could work and deliver the results we [6:23] wanted. And then when we had confidence in [6:25] that, we said, oh, okay, cool. Now what [6:26] do we do about syntax? Right. I have to ask, [6:31] what's it like to write MLIR? So MLIR, if you're not familiar with it, [6:39] it's like, you know, so Mojo is too swift as MLIR is to LLVM. [6:44] So LLVM is super widely used. It's 25 years old-ish at this point. It was [6:51] brought up in a mode with a philosophy of there should be one IR to [6:55] rule them all. It should be the LLVM IR that many, [6:58] many compiler folks are familiar with. And that was great for a generation of [7:03] things that look basically like C, or you could desugar down into [7:06] something that looks basically like C. And so LLVM is, you know, I kind [7:10] of joke it's C with vectors plus exceptions, [7:12] or C with vectors plus debug info or something like that, right? So it's in [7:16] that kind of category of representation. But again, when you [7:19] start getting into GPUs, other accelerators, what you [7:22] end up wanting is multiple levels of abstraction, something more like, you [7:26] know, the Haskell GHC compiler or something like this, where [7:28] you have many different lower lowering phases, and you're [7:31] exposing different optimization opportunities to different levels of [7:34] abstraction. And so in 2018, I led a project to build this thing [7:39] called MLIR, which is a replacement for LLVM that allows making [7:43] domain specific compilers really fast. And so it provides a bunch of the core [7:49] compiler infrastructure, the IR representations, the pass [7:52] managers, bisecting tools, like the ability to parse and print IR and [7:56] all this kind of stuff, and allow you as a compiler hacker to be able [8:00] to focus on your domain. And so you can model your design, your type [8:04] system, you can design the structure of the operations that you [8:07] want to manipulate and things like this. And so MLIR is a very useful [8:11] Swiss Army knife for building domain specific compilers. I've used in [8:14] the past to build like hardware synthesis tools, like all [8:17] kinds of stuff. And so that's what we're using. And one of the great [8:22] things about MLIR is it has a text form. And so you can just write the [8:24] text form. Okay, but I'll say writing an error by hand is [8:28] really painful. I mean, that's not actually a good user experience. It's [8:31] something that you can do to prove a concept, but you never want [8:35] to expose that to users. Just imagine it's a pretty fuzzy [8:39] question. But is it lower level than C higher level, [8:43] just different? It's it's domain independent. And so you can [8:47] use it to do like machine level code representation, if you'd like. And a [8:52] lot of people do that for for accelerators and things [8:55] like this. MLIR is widely used in the machine learning, co-generation [8:59] community, for example. But we use it for AST. And so you don't [9:06] need to use it for any particular thing. And in the case of [9:08] Mojo, we don't build an AST traditionally, we actually just generate [9:12] MLIR directly from the parser. Okay. Okay, so then in that case, [9:17] we have to go both down into the hardware and see what you [9:20] did with that. But why don't we go up into user space [9:23] before we get those leads? Just briefly. So you've proved out your [9:28] theories to a degree that you say you want to send this [9:32] approach to the world. Now it's time to put lipstick on our pig. [9:39] Yep. Or on a video. [9:42] Let me use the git metaphor. We'll put "porcel in" on the plumbing. [9:46] Yeah. So, and you've chosen to go quite close to Python, right? [9:52] Yeah. Why that? [9:54] Yeah, so when we decided, okay, this seems to be working, we [9:57] think we have a novel and useful co-generation approach. We had to decide [10:03] how we're going to get this IR. And there's a couple of [10:05] different approaches. One is, and by the way, building a [10:08] programming language is insane, and we can talk about why. But the [10:13] obvious thing to reach for is a domain specific language [10:17] embedded in some other language. And so use, for example, Python [10:21] and use some decorator-based approach or some way to stage out [10:25] something and then generate IR by walking some other [10:28] languages AST. The other approach is you say, okay, go build a language. Another [10:34] approach might be to say, build a source translator or [10:37] something like that. And so there's lots of different technologies [10:41] that we can use. And so in our case, we're targeting this AI [10:45] world. We're targeting this emerging world of high performance [10:48] accelerators, GPUs, everybody's dying right now because of [10:51] how complicated this stuff is and then how challenging the [10:54] programming model is. And so we decided, okay, let's do the hard [10:57] thing. Let's eyes wide open. We understand how hard it is to [11:00] build a programming language. Let's do that. And we think the cost benefit [11:05] tradeoff is worth it. And let me tell you why it's a bad idea [11:08] to build a programming language. I mean, you probably know, [11:11] but it's not just about building a grammar or a compiler. You also have to [11:15] build all the tools. You have to build code form routers, and [11:18] you have to build a debugger. You have to build this entire [11:22] ecosystem. You have to have a library ecosystem. You have to have developers [11:26] who care. You have to build the technically difficult thing in [11:30] the right way. And so there's a lot of design and [11:33] tech. Yeah, package manager and LSP and Slack channel. Yeah. [11:37] That's right. That's right. And so in the case of Mojo, we said, okay, [11:40] well, and as you know, I've been through that with Swift. And [11:43] so yes, we built, we bike shaded all the syntax, we built all the different [11:47] things. And so what I realized is that I want to control some [11:50] of the risk, but also meet developers where they are. [11:54] And in AI in particular, Python won. Like Python is nothing. Yeah. And [11:59] so everybody uses Python. And so if you want to pick anything not [12:04] Python, you'd have to justify why not pipe, why, why it's better [12:07] than Python and saying, okay, I have curly braces, a set of tabs, like isn't [12:12] actually a great answer, because at the end of the day, while I [12:16] and you and many people of programming languages, [12:20] people have muscle memory. And so I care about the hundreds of millions of [12:23] developers who already know Python, right? And I'm not having to [12:26] retrain is actually a huge feature. From an engineering [12:29] and design perspective, it's also very useful, because we already [12:32] know what the language looks like. Right. So we don't have to bike [12:35] shed all the things. It's way easier to implement something [12:38] when you know what it is versus having the first principles, [12:40] everything and, and have to rationalize this. Now, yeah, Mojo is a very extended [12:45] version of Python, we could talk about what it's all about, [12:48] but there's still design work, but at least we could focus our energy. [12:52] Yeah, most of those early decisions are made for you. [12:55] Yeah, exactly. And so like, for example, Python uses this fairly [12:59] goofy postfix turnery thing with you know, the if goes after the condition [13:03] and stuff like this. Oh, yeah, yeah. That is not my [13:05] personal cup of tea, but it doesn't matter. It is proven exists, it works. [13:10] And if we were to change it, we'd have to massively justify why we [13:15] want to break compatibility or break familiarity or [13:18] break all the training that people already have. So it just really anchors [13:21] the project in a very convenient way. Okay, yeah, yeah, I can [13:24] see it. I have to ask that if you're, if I were building a [13:28] language that was focused on like high performance and optimizing [13:31] for GPUs and all that stuff, I would be torn between going after the [13:35] ML data science world and the gaming world. [13:39] Yeah, you could have gone for those, but you could have gone for [13:42] PlayStation five programmers, right? Sure. And there's a lot of money [13:45] in that. Did it tempt you? Well, so not really, honestly, just [13:52] because we're mission driven, we have a we have a specific thing [13:55] with GPUs and accelerators and AI. And this problem is boring. [13:59] I've been in the space for five, six, seven years at this point. And [14:02] so very much on that track. But without loss of [14:06] generality, mojo can be used for lots of different things. And we [14:08] have people building like GUI libraries and web servers and everything. [14:12] And so it's a general purpose programming language. [14:15] We could talk about the nature of the language, but the, but it is fully [14:18] general purpose. It's just that our design points were rooted in our [14:23] use case, and the problems that we're trying to solve. And [14:26] there is no language out there that does what mojo does. And so [14:30] solving for those, you know, that was another option is just use [14:33] somebody else's language, right? And so if there's another [14:36] language out there, it would be great to just not have to do all this work, [14:39] because we could get on with life and focus on other parts of the [14:41] problem. So yeah, yeah, I can see that. I can totally see [14:44] that. So before we get into it, I will say we do we do have a number of people [14:49] on our team that are coming from the games industry. So okay, [14:54] so you've tempted you've at least tempted some of that [14:56] audience across to Yeah. Okay. So before we get into what makes mojo [15:01] different, let me just quickly ask, I've written plenty of Python, if I [15:05] came to mojo, how familiar would it be? Would it feel [15:09] exactly the same until I started using the new things? Yeah, so [15:13] mojo is not done yet. It's probably halfway through his development [15:16] journey, I would guess roughly. But when it's done, it will [15:19] be a full super set of Python. And so if you're familiar with [15:23] Python, then you know about the Python two to Python three transition, [15:26] just about killed everybody involved sucked energy out of the [15:30] community for 15 years, it was it was kind of a gigantic mess. And [15:33] the reason that that happened is because it was, you know, similar but [15:37] different and packages could not interoperate with each [15:39] other, you couldn't have a hybrid half Python to half Python three program. [15:44] Yeah, and so it became exactly. And so that was a huge problem. [15:48] And so in the case of Swift, what I learned is, [15:50] I mean, Swift is a completely different language than Objective C. [15:53] But what we did was we very successfully migrated over the course of [15:57] years, but progressively migrated the Objective C community [16:00] over Swift. And we did that by making it so both worlds could live [16:04] together. You can call one from the other happily. Exactly. And so that [16:08] way you can decide, okay, well, this third party package [16:11] I'm using, I'll leave it as Objective C, but I'll write my UI or whatever it is [16:16] that I want to do in Swift. And, and I'm not in this log jam [16:19] where everything has to move over. And so in the case [16:22] of mojo, right, we're building it into a full super set of Python. And [16:26] so all all the Python idioms and stuff like that, whether they're a [16:31] good idea or not will work in mojo. But even today, [16:35] you can import arbitrary Python packages and go to town and use [16:38] them. And you can mix and match very directly. And so we're continuing to [16:42] make progress on more dynamic features in particular, [16:45] because as you say, we're climbing, we're climbing from the [16:48] accelerator. So it's mojo is a really good replacement for CUDA. We're getting [16:52] into the it's a really good replacement for Rust. And then [16:54] eventually we'll get into the it's a good super set of what Python is [16:58] loved for. But, but we have to do those steps. And we have to build [17:01] out the features as we go. Yeah, yeah. Yeah. No matter [17:04] what happens when you're writing a language, you're climbing [17:07] some kind of enormous mountain. Yeah. And that's the shape of yours. So [17:12] does that, speaking of the size of that mountain, [17:15] does that include things like this, do you support Python's interop with C [17:22] syntax and approach? We haven't decided that actually. So, so [17:28] one of the very big, so as if you're a Python program, [17:31] we're looking at mojo. One of the things that's really interesting [17:33] about mojo is that it is Pythonic. And it is it's growing into all [17:37] the different dynamic things that Python can do, [17:39] but you don't have to switch to a different language to [17:42] write high performance code. Right. So if you think about Python, [17:46] Python, like Objective C, actually, since you're a veteran, [17:51] Objective C and Python both have the fully dynamic object [17:54] oriented, we want all of our APIs to be built in objects world. But [17:58] then it has the dark truth of, you know, all the important [18:01] stuff is written in C or C++. Right. And so a lot of you look at [18:06] NumPy is just one example, it's a very nice Python API, but it's all [18:09] written in C, C++, wrapping until MKL and all this kind [18:12] of stuff. Yeah. Right. So with mojo, you can write all of that stuff in one [18:15] language. So you don't have to switch out. And the way that [18:18] works is it's a progressively typed language. And it has [18:22] real types, not the my pi types that Python currently has. And [18:27] so plus it has really fancy compilers on next generation stuff that [18:31] that has been created over the last couple of years from, [18:34] you know, learning from decades of other stuff that got built. And [18:38] so the consequence of this is that you don't have to switch out. And [18:42] so that integration with C, the reason it's challenging is [18:46] that Python exposes its full object model to C code. And so we [18:52] actually fully support that right now, because we can talk to Python, [18:55] we can talk to Python C modules. And so that already [18:57] works. But there's a question at the low level of like, do we want [19:00] to support that like really low level binding when talking to C [19:04] bindings? Or do we want to encourage the community to just switch [19:06] stuff to mojo or not? And so we haven't, okay, we'll figure that [19:09] out. So it may be in the future that whilst you can't use the Python [19:12] wrapper around the C library, you might find it very [19:17] easy to go direct to the C instead. Well, in mojo can already call [19:21] it a C. And so that's all. Okay, so you've you've pricked my ears on [19:27] one of my favorite topics, which is types. [19:30] Yeah. Because you've got, I read on your website, you've got a [19:36] progressive type system. Yep. [19:38] In mojo. And I actually don't know what that is, because it's not the same as a [19:42] gradual type system, right? Yeah, so maybe I'm not being very [19:46] precise on terms. I'm also, by the way, an engineer, [19:50] I'm not a mathematician. Okay, so just as a disclaimer, and so I, [19:55] but sure. So what's the question? How can I? So, so tell me about [20:00] mojo's type system? And is it opt-in? What kind of type [20:05] system is it? How much do I have to learn to use it? Yeah, okay, so all good [20:11] questions. So start with, how do you get a typed language to talk [20:16] to Python? So this is the very first question, [20:20] then you then you have to ask, what is the existing Python type system? [20:25] Right. And if you ask a lay programmer, they would typically tell you, oh, well, [20:28] Python doesn't have types. Right. And then if you talk to a [20:32] more advanced developer, they'd say, oh, it has dynamic types. [20:35] Right. And so there's a list, there's a dictionary, [20:37] there's this stringer and int, but it's all runtime. Right. [20:40] Yeah. As somebody who knows programming languages and likes some [20:43] static languages now and then, we can say Python has [20:46] one type. And that one type is a reference to a Python object. [20:51] And because there's one type in Python, you never spell it. And so that's [20:56] how I would say Python is it actually has a static type [20:59] system. It just has one type. Okay. Yeah, I can see the argument. [21:03] So now if you go down that direction, you can say, let's give this [21:06] thing a name. And so in the case of Mojo is called [21:08] Python object. We'll decide if we really want to consider it [21:11] Python object forever, if we want to shorten it to object, but [21:14] it has a name, it's called Python object. And now you can say, Hey, well, I have a [21:18] new type. I'm going to call it int. Or string or whatever. And so when I say [21:23] something is an int, that's a different type. [21:26] Okay, I can have conversions from one to the other. And I can I can [21:30] make these things integrate and operate. But if you're a programmer, [21:33] you can say, Hey, this thing is an int. And now of course, [21:35] it's not boxed. Of course, it's on the stack. Of course, it's [21:38] you know, the size of your the word on your machine or whatever, [21:41] right. And, and of course, it works the way it would work in [21:44] CRC plus plus or something like this. And so you can have the ability [21:48] to opt into to a fully static world. And so again, we work with CPU and [21:53] GPU high performance numeric programmers, they never want anything dynamic, they [21:57] want full control over the machine, they want full control [21:59] over very fiddly low level optimization things. And so you don't want these [22:04] worlds where it's like, Hey, I'd write some dynamic code, and [22:06] we'll try to de virtualize it. That community wants it's like [22:10] the the rust ideal in many ways. It's like I want full control, I want [22:14] predictability, I want you out of the way. And so we can provide [22:17] that. And then if you start removing types, you can get [22:19] fully dynamic if you'd like. Okay, so if I say that something is a [22:26] is it I'm thinking of pure script here where I can say this thing, [22:31] which is just a foreign thing coming from the world of [22:33] JavaScript, I declare it's a string as now you're going to treat it like it's a [22:38] string. And it might be almost anything under the hood. Yeah, [22:41] we're we so we are not in the mode of so there's a [22:44] whole class of languages including TypeScript and even Python [22:48] itself where they're saying the fundamental nature of the universe is [22:51] untyped, but you can provide type hints. And those type hints [22:56] can be used in for error messages or other things like this. We're not that [23:01] that is not what we do. Okay, so we have we have types and we [23:05] have a Python object. And if you want to go from [23:08] Python object to an int, you do a conversion. Okay, so there is [23:12] it. It's not that conversion is checked. And so okay, there's no like, [23:18] trust me, it's gonna be okay typing, it's it's actually [23:20] typed, like, and this, this is actually very important. And so, [23:24] and then the nice thing about this is it all composes correctly through [23:26] the type system, which is, you know, the big thing. [23:30] If you dig into so that that's the very top level, how do we [23:33] handle progress, what I would call progressive typing, maybe it's the [23:36] wrong word, I don't know. Again, I'm still new to [23:38] languages and some work on this stuff. But the but within the stack [23:43] type system, then you can say, Okay, well, how does it work? Well, it's [23:46] both very boring in some ways. But it's also, I think, [23:49] very boundary pushing and others. And so it's boring in that it [23:52] uses like, you know, we learn category theory, we understand how, like [23:56] traits and rust and protocols and Swift and like all these [23:59] things work. And so we're just taking, you know, modern statically typed [24:02] generic, higher order functional type system like many modern [24:06] languages have and bringing that in. And I don't think [24:09] anything I mean, it's, it's nice, and it's important to get [24:11] that right. But it's pretty familiar to people. And I think [24:14] familiarity is good. The, the other side of it, though, [24:19] is that we are very hardcore about pushing things into the library. And so [24:24] if you take a look at rust, for example, but in this case, I'll [24:27] pick on C++, because it's an easier victim. C++, [24:32] it's a it's a very powerful language, you can build high, high [24:34] quality libraries in C++. But, but because of its historical roots, it [24:38] burns a whole bunch of weird things into the language. [24:41] And so for example, complex numbers are STD complex, a template, [24:46] but float and double are built into the language. And there's [24:50] certain things, certain conversions, certain weird [24:53] things that only work with built ins that can't be exposed out to [24:56] libraries. So for example, you can't overload operator dot in C++, [24:59] you can't build a smart reference, right? It's just a super, [25:02] I think that's one thing that's been driving Bjarne nuts for [25:04] decades now. But and so in mojo, we take a very aggressive approach on [25:10] this, which is say, push everything we can into libraries and [25:13] push the magic out of the compiler. And so, and so int is not built [25:19] into language float is not built in language, like these things are [25:22] all just libraries. And so they're just structs. [25:25] And so the way this works is that, you know, they're the type [25:29] system composes, and we use it for all the built in things and yes, drag [25:33] and array and all these things, of course, are also [25:35] written library. What that forces that forces the language to [25:39] provide only the core essentials for expressing libraries. And we want [25:44] everything to be ergonomic and very dynamic and flexible and [25:46] powerful for the Python folks, etc. And so by doing this, we, you [25:50] know, the compiler language library divide is balanced a little bit [25:55] differently than what you'd see in traditional languages. [25:57] Right, yeah, this is reminding me when I first learned in Haskell, [26:01] that Booleans aren't that yeah, they're not caught of the language. [26:05] It's just, they provide you the tools to define Booleans. [26:09] Yeah, otherwise, it's just an alias for true. All right. [26:13] Okay, so so how does that actually work if because I see attention [26:17] there between all the main types are kind of user slash library space [26:23] defined. And I want really, really high performing optimizations [26:28] for an array of ints. Yep. Well, so on one side, old tricks are [26:35] the best tricks. And so Mojo believes in zero cost abstractions, for [26:38] example, and so zero cost abstractions are seen in C++ [26:41] and Rust and many, many languages and so nothing wildly innovative. [26:49] The way we do it is pretty innovative because we have this fancy MLR [26:52] compilery stuff behind the scenes. But but the concept is [26:56] the same. But what that does is that allows you to stack up [27:00] turtles. Okay, so you can have a lot of turtles and we're good. We love [27:05] abstractions. And so we can we can stack up turtles like anybody. [27:08] But you have to have something where you bought them out. Like there has to be [27:11] something underneath that bottom of the turtle. Right. And so [27:14] Mojo by design, it takes a lesson from Swift and then [27:18] takes it 10x, which is in Swift, I sometimes used to joke that Swift was a [27:23] syntactic sugar for LLVM. Yeah. So Swift int was also defined in [27:29] the library. Swift int was also a wrapper for an LLVM [27:33] I32 or I64, you know, the underlying IR thing. And the way that [27:37] worked is that Swift at the very bottom could talk directly to LLVM [27:40] primitives. And so what you're doing is you're building [27:43] syntactic sugar, you're defining types and therefore [27:45] overloading operators on and doing all the stuff to build up these core [27:48] operations. Mojo does basically that same trick, but it [27:53] supercharges it by moving to this MLIR world. And so MLIR being a much more [27:57] modern compiler stack has way more powerful features. We can expose [28:02] things like, you know, float four and make these really [28:06] weird numeric CC on accelerators. We can do all this, like very, again, we're [28:11] talking to accelerators with tile matmoles like the Tensor Core [28:13] on GPU and things like this. And so we can talk to [28:16] all these really exotic features and then wrap them in really nice [28:21] libraries. And so you get the benefit of the power of the hardware [28:24] and direct low level access to very crazy exotic things. [28:27] But then you have syntactic sugar built in libraries and now [28:30] you can extend the system, extend the language without having to be [28:34] a compiler nerd, which I think is very, very important. [28:38] How does that actually look? Because that sounds fascinating, but I'm wondering, [28:44] let's say I decide that I'm going to write a complex number library for Mojo. [28:51] It's simple and because I'm writing it basically in Python. [28:55] Yeah, you have a structure two floats in it and then you go and [28:58] overload the underbar underbar add method, which is the Python [29:01] way of overloading the operator plus. Right. And so, yep. [29:05] But at some point, am I going to say, oh, I can tweak this if I just [29:09] mix in a bit of MLIR code? Yeah, if you'd like to. So for example, [29:14] use complex numbers. Complex numbers are hardware [29:17] accelerated on certain chips. And so it's not just like add of two complex numbers, [29:24] because you're just adding two floats. But if you do a multiply [29:27] accumulate or if you do a complex multiplying, it includes, I mean, my math [29:32] is rusty, but it's like four multiplies and a couple of [29:34] adds or something like that. There are these certain CPUs have [29:40] operations that just do that in one shot. And so you could say, okay, [29:44] well, effectively like an if def, we have a compile time [29:48] meta programming system that you'd use to do this instead. But [29:51] effectively like an if def, if def among this system, I have this [29:54] feature, go do the optimized thing else, just do the generic [29:58] thing. And then you have full access. So I can do opt in as a [30:04] library writer, I can do opt in hardware level [30:07] acceleration. That's right. Yep. Yep. And still have a nice [30:11] fallback. Okay, that's fun. And and your clients don't have to worry [30:15] about it. And that's actually a really powerful thing. [30:18] And would I be able to say things like if I'm on this [30:20] architecture, do this and if I'm that I'll do that. And if it [30:25] fails, just use Python stuff. Yeah. And again, Lojo has superpowers [30:29] because of the domain it's in. So you can write one piece of [30:32] source code and that source code runs partially on your CPU partially on your [30:36] GPU. And these may have different pointer sizes and may have [30:39] different numeric and capabilities. And the way the whole [30:41] stack works is it supports this code sizing thing. And that's, you know, [30:45] there's these very deep, fundamental, very nerdy compiler things [30:49] that enable things to just work in a way that people [30:52] aren't quite used to. Okay, this is fun, because this means like, [30:56] potentially, you could see a future where someone writes a really [30:59] useful library, but it's not fast enough. And someone [31:02] just PRs in the hardware optimization without changing the [31:05] programming language. Yeah, well, and also we've, so again, [31:08] Mojo designed in 2022, instead of 2000 or 1980. [31:16] You know, we have, we have things like SIMD. And so SIMD vectors [31:20] are a thing, all computers have them these days, we have direct support [31:24] for that direct support for explicit vectorization. [31:27] So you get full access to the hardware. And so it's been really [31:30] fun seeing Mojo developers worldwide where this takes something [31:33] like, you know, game of life or whatever, and they just say, [31:35] okay, I'll start using this, I'll try this. Oh, hey, wow, it's 1000 times [31:38] faster than the code I started with. That's cool, right? You [31:42] know, just because again, with library based extensibility, [31:45] our vectorized function, it's just a library function. And so [31:48] it's like, okay, well, I will vectorize this code by using a combinator [31:51] from the library and just going to build into this one step [31:54] at a time. And I've seen tons of people go through this growth path through the [31:57] go out, this is really cool. And oh, wow, I'm having fun. Oh, [31:59] wow, I'm building something interesting. Oh, I'm learning [32:01] something, right? And this is where I think people love going [32:04] through the growth path. Okay, well, in that case, we have to get [32:07] down now into CPUs and GPUs properly, I think. Sure. So [32:12] what is it that you what are these theories that you proved out in MLI, MLIR [32:19] space that make Mojo compelling to you? Well, so the we [32:25] probably shouldn't dive deep into that, because we can [32:28] say in the language stuff, but I'll give [32:29] you some intuition. So in the in the AI space, [32:33] so I'm in love with AI for both the user applications, which is [32:36] what most people talk about, but also all the systems and all [32:39] the technology that got built to support this. [32:42] And to tell you one thing that I find fascinating is that today, so [32:46] I worked on the TPU project at Google, and so help bring up these [32:51] massive data center accelerators with exaFLOP computers, [32:55] right? They're supercomputers with thousands of nodes and all this stuff. [32:58] And one of the things I found just super inspiring is that we [33:01] have today, you can sign up for a Jupyter Notebook on Google [33:05] Cloud and get access to all these things. And with a few lines of code, [33:08] you can now be programming an exaFLOP supercomputer. And you're [33:12] describing a novel computation and it gets mapped, [33:15] partitioned, scaled out across thousands of chips, run at like massive data center [33:22] speed. And this is what HPC people have been doing for a long [33:25] time. But now you have AI researchers doing this, right? They're [33:28] not they're not writing MPI code or low level [33:32] high performance stuff. And so what what enabled that is that enabled [33:37] or what what what made that possible was a shift from completely [33:41] imperative programming to declarative programming. [33:44] Okay, and the way this works is in AI, you build a machine learning [33:49] graph. I mean, there's many variants. But for example, you build a [33:51] machine learning graph. And you have the AI researchers [33:54] thinking about the level of, hey, I'm gonna have a matrix multiplication, I'm [33:57] gonna have a convolution, I'm gonna have gather reduction or [34:00] whatever. And so I'm thinking about it's almost like APL, [34:04] again, bring it back to language and rotary, right? And so they think about [34:10] simple compositions of these, these highly parallel operators. [34:15] And then what you do is you give this graph to a very fancy [34:19] compiler stack, which then takes this and does not just picking out [34:24] functions, implement each of the operators, but it's actually doing [34:26] fusion of the loopness. And so you're taking, you're taking [34:31] this very complicated math, doing very high tech compiler [34:36] transformations, and then also dealing with distribution across clusters. And, [34:41] and these things you can do because it's a declarative [34:43] specification. If you try to try to take a pilot c++ code and parallelize it, [34:48] right? Well, good luck with that. That's not a thing, right? But [34:52] if you say, hey, run four copies of this across four [34:54] machines, well, that's easy to do, relatively speaking, right? [34:58] And so, and so what what this whole stack evolves into, in the case of [35:02] Mojo is we have what's called the max engine. The max engine [35:07] is a very fancy AI compiler stack. It is, it's kind of like an XLA, [35:13] but after learning a lot of lessons familiar with these things, and [35:17] so it can run machine learning graphs, but we want it to be [35:20] able to talk to the imperative code. And so you need to be able to [35:24] write custom operators, you need to be able to invent new algorithms, you [35:27] know, if if modular doesn't know what an FFT is, but you do, [35:30] and that's really important to your signal processing domain, [35:33] then you need to be able to provide an FFT. But we want the stack to [35:36] be completely extensible. And so what Mojo enables [35:40] people to do is you can write an algorithm, very simple, familiar code, [35:43] it's all it's all good, you can understand it because you're just [35:46] writing source code. In contrast, CUDA is kind of its own [35:50] little world. It's very not Python, right? And so, and so [35:54] instead of writing a CUDA kernel, you can write some Mojo code, and then [35:57] the graph compiler and the other stuff can suck this up, [35:59] because because of MLIR, we can now reflect onto it, and we can [36:03] see what the code is doing. And so that allows us to take it and do [36:07] these fancy compiler fusion things and do the placement, [36:10] do the route, all the stuff. And, and that's something the [36:13] world doesn't have. Because in the AI space, the state of the art [36:18] technologies, I mean, there's a lot of stuff out there is very [36:20] crowded space, but the state of the art technologies are built around CUDA. And [36:25] they're built around math libraries like Intel, MKL, and [36:28] things like this. And these operators are all black boxes. [36:32] And so there exists these fancy graph compiler things, but they [36:36] don't actually have the ability to see into what the logic is that [36:41] they're orchestrating. And so they can't do these high [36:44] level transformations, and it just is very janky in various ways. [36:48] And so again, our part of our mission is to like solve this, take all [36:51] these systems, a major step forward. And so this is [36:54] what drives, you know, Mojo needs to have extremely high performance, right? [36:58] Because we want to push state of the art on performance versus [37:01] vendor libraries that do matrix multiplications, [37:03] for example. It also is why we care about usability, because we [37:06] have people that are using the same thing to build graphs, and [37:09] they're used to Python. And so we want to meet people [37:11] where they are, you know, they're used to PyTorch or something [37:13] like this. And so, you know, it kind of all flows together. And [37:17] that's, that's where we're coming from. Okay, so there is, there's a hard divide [37:22] between the world of building up this data graph, [37:25] and building, creating custom nodes that you would insert into that graph. [37:31] Well, and then and then, yeah, and then to make it even more funny, [37:34] like, I don't know how deep you are in the space, but it's so funny, [37:39] because the traditional TensorFlow PyTorch things were [37:42] designed eight or 10 years ago, depending on how you count. They're [37:46] coming from a research world, they're coming from an AI training world. [37:50] But today, roughly everything, not everything, [37:53] a huge amount of the focus of the AI industry has shifted to deployment. And [37:58] so when you get into deployment mode, and you're shipping and [38:01] running an AI model on a server or something, you don't [38:04] really want Python in production. And so it turns out there's some challenges, I [38:10] mean, it can be done, but there's some challenges with that. [38:13] And so, and so what we've entered into this world is we have [38:16] researchers who love Python and live and die and breathe Python, and, [38:20] and it's great for their use case. But then you have production people [38:23] that have to rewrite these models and rewrite the [38:26] tokenization logic for your LLM in C++ or Rust to be able to ship [38:31] something. And so a big part of what Mojo is actually about is by solving [38:37] that problem by having one language that can scale, [38:40] we can heal this divide between all the personas that are building [38:43] these systems, whether they're high performance, numeric people, whether [38:46] they're deployment engineers, whether they're AI [38:48] researchers, and get just get everybody to be able to talk to [38:51] each other, because they're literally speaking different languages, [38:53] and they, they and you're massively impacting AI getting [38:57] into production. I had no idea the AI world was divided like [39:01] that into different hats. Yep. Is that sharper? And yes, that [39:05] Conway's law striking again. Well, it's an evolution of a lot of very, [39:11] very good, very well considered systems that were [39:14] locally developed, aggregated, and then he'll climb like crazy. [39:19] Because AI has changed a lot in the last five to eight years. And, and [39:23] nobody's had a chance to go back and first principle some [39:26] of the technology, right? And you look at that eight years in [39:29] computing is nothing, right? That is, that is nothing. And so all this stuff [39:34] grew really quickly. And so, you know, this is this is where [39:37] you say building a programming language is insane. Well, I mean, this is my [39:41] words, not yours, you're too polite to say that. But but the, you [39:46] know, I don't think it's insane. It's just a multi year [39:48] project. And so you can you say, Okay, well, what are the benefits [39:53] and the costs and benefits of doing that? Well, you have to be very [39:57] practical about this. And you have to make sure to not sign [39:59] up for something you can't deliver on. But you know, if the [40:02] results are worth it, like it's a big bet that lots of other people aren't [40:06] willing to take for a wide variety of reasons. And so you [40:09] have to be right. But if you're right, then it's actually a really good [40:12] contribution to the world. Yeah, yeah, I think if you've got a good [40:15] enough reason to create a language, then I don't think it's insane at all. [40:20] And if you have no reason to create language, [40:21] but just fancy as a hobby project, then it's also cool. I love that too. [40:25] But there's something in that middle space, which is definitely [40:27] kind of crazy. Yep. Yeah. Yep. Okay. I have to ask, because I don't know [40:35] much about this world. But if you're writing one of [40:38] these operators within a machine learning graph that you've [40:42] described, what's that like in Python-esque mojo programmer space? [40:49] Because it feels like it's going to be something like [40:54] pipelines, like I'm going to yield a value and a weight of value. [41:00] Also, it depends on what part, what kinds of code you're building. [41:03] But I mean, the analogy is, it's kind of like writing C++ or Rust [41:07] code, but with Python syntax. And so you get rid of all the [41:12] templates, you get rid of all the line noise, but you're [41:18] writing for loops. And so mojo, because it provides higher level, higher [41:24] functions and I mean, commonators that you build in the [41:27] library, you're often composing together, "Hey, parallelize this [41:30] region, vectorize this region." And so the code style looks a little bit [41:34] different than maybe literally just writing for loops. [41:38] But mojo is disarming to people because people are taught, for example, [41:42] never write a for loop in Python. Python is slow. Never write a [41:46] for loop in Python. And so in mojo, all that wisdom is invalid, [41:51] because it has none of the DNA of Python. It's not the [41:56] same implementation. And so a lot of these things that people [42:00] knew to be false are actually totally fine. It's also super funny. We [42:05] have folks that are writing high performance Tensor Core [42:09] stuff and VNNI low level stuff. And they're really experts in low level [42:14] system architecture. And they're like, it's so weird to be [42:16] writing assembly code in Python. Yeah, that's weird. [42:22] And so like, it does twist your brain or open your eyes or shift your perspective, [42:26] however you want to look at that. But otherwise, it's familiar. And [42:31] again, it's not a lot of what we're going for isn't driven by novelty, [42:34] for novelty's sake, it's about pragmatism. [42:38] One thing I'd love to talk about is the compile time [42:40] metaprogramming piece of this as well. And so yes, okay. Well, why don't we go [42:44] there now? I've got a couple of other questions for you. [42:47] Well, so I mean, this is another big bet that we've made. And so [42:51] in these domains, both in the AI world, where you're building models, [42:55] models and source code are effectively a metaprogram. They're [43:00] a bunch of imperative logic. And then they describe roughly a [43:03] graph. And that graph is the thing that then you distribute [43:07] and transform and do whatever. And so Python has long been used for [43:11] metaprogramming for a wide variety of different domains. But that's [43:14] one of the reasons it's been very successful in the AI [43:16] community. If you look at the new, again, this the other the other [43:20] world, the high performance numerics, people often use C++, and they [43:24] use templates. And you're metaprogramming these [43:26] things because you want an algorithm that works on both floating [43:29] point and on double or float 32 and float 64. Right? Yeah. And of course, [43:35] then it turns in this massive cataclysm of templates and [43:39] depending on how advanced you get, right? Also more modern languages, for example, [43:43] I know, you know, Zig, for example, has said, Okay, well, let's not have a [43:48] different meta language than a language. Yes, right. Let's [43:52] actually use the same language for the metaprogramming as for [43:54] the programming. And so again, in case of Mojo, we're learning from [43:59] the good work of many other domains. And so we said, Okay, that's [44:02] actually a really fantastic idea. Python is highly dynamic, [44:05] you can overload operators, you can do all these things [44:08] dynamically. We can't pay the expense, we can't have even a single clock cycle [44:12] extra in our domain, right? We have to have bare metal, [44:16] bare metal performance, but we want the benefit of the abstractions [44:19] and the extensibility that Python provides. And so what we do is we [44:23] say, Okay, let's take the benefit of the Python, [44:25] let's do everything dynamic. Let's take comp time metaprogramming, let's fuse [44:29] these things. And this is one of the major ingredients that [44:32] allows Mojo to be extremely expressive, because you can [44:36] just like in Zig, but I mean, we have a slightly different take, but the same [44:39] idea is Zig, you can build the standard runtime algorithms, [44:42] you can allocate heap data structures, you can do all [44:45] this stuff and then use it at compile time. And so you get this [44:48] composition that enables really expressive libraries, and nobody likes [44:52] C++ templates, right? And stuff like this. And so [44:55] you get the benefit of building these things, which gives you [44:58] the ability to build these combinators and these higher level [45:02] functions and features and compose the benefit of this [45:06] compiler world, plus the runtime world. Okay, so to be clear, are we [45:11] saying that you're introducing a thing where I can write, it looks like [45:15] I'm writing Python at compile time to generate Python [45:20] to then compile and run? Yes. Or another way to say it is you [45:24] have values and objects and functions and features and classes and [45:30] types and things like this. And you can use them either at [45:32] compile time or runtime. Okay, but I can start constructing my own [45:37] abstract syntax trees at compile time. We haven't gotten that far. [45:43] But in principle, we could support that. But it's more of like a simple example, [45:47] as you say, okay, well, I have a function that creates [45:51] a lookup table. Okay. Okay. And so it's a normal function, you can [45:55] call it at runtime, you can pass dynamic values and as the arguments. [46:00] Cool. Give me give me a STD vector, we call it a list, [46:04] but like, give me give me a dynamic collection of values that are populated [46:10] through whatever crazy math you want to do. And I say, Okay, [46:13] cool. That lookup table is static. And the inputs to the [46:16] table are always static. Just go call that at runtime and just [46:19] give me the table. And so what it does is it says, Okay, just a compile [46:23] time, go run that function, calculate the dynamic data [46:26] structure, do all the logic that you're doing. The output of that [46:28] is an object, it's, you know, a list, burn that list into the [46:32] executable. And now you have an object, and you just have the [46:35] object directly instead of having to compute it. Now, and that's a simple [46:39] example. There's many fancier examples because when you when [46:44] you do this, suddenly, as a type system nerd, maybe you'd [46:48] appreciate that, you know, like types are just values, right? And so [46:52] you can and so your types are just compile time values. And so you [46:56] can do much more fancy, higher level programming at [47:00] compile time with using types as values and things like this. And so there's, [47:04] there's a whole rabbit hole there. But it's the cool thing about [47:07] is that it comes back to enable enabling library developers [47:10] to make demand specific abstractions and build things that allow [47:13] modeling their world very clearly. Okay. I remember talking with Laura's [47:19] crow about Zig how we were saying that that would be a way [47:22] in to make like specific take a generic list, say, compile time [47:28] make the optimized version. Yep, same idea. And of course, Zig has [47:34] its own personality as well. And so it's a very low level [47:36] language, it issues syntax sugar and things like this. And so it's [47:40] very, you know, has it has a it's very different in certain ways than [47:44] mojo. Mojo wants to enable libraries and abstractions. [47:48] And so that's, that's its focus. But this this use of comp time and [47:51] that idea is very, very common. We're very happy to learn and admit that [47:54] we learn from other people, we didn't invent everything. [47:56] Now, we all stand on the shoulders of giants, right? That's [48:00] right. Exactly. And I'm sure they were inspired by Lisp, which goes all the [48:03] way back to the start. Yep, yep. Everybody's doomed [48:06] to re implement their own list, right? Yeah. Yeah. And that's not [48:10] crazy. That's a good learning exercise. Maybe shipping is not always a [48:15] great idea. But okay, so we've actually not tackled [48:22] this, but we've skirted around it the whole discussion. The [48:26] moment you're going from Python into real low level, dealing with CPU [48:32] stuff, surely the idea of the idea of memory management [48:37] is going to leak in here. Tell me what you've done there. Yeah. So [48:43] if you're dealing with Python object, so one of the ways that we can [48:47] embrace the entire Python ecosystem is we just keep [48:50] the CPython object model. And so everything is just [48:55] compatible. And so if you import Python, you get the traditional reference counted [48:59] indirect object box thing. And that's that. That's cool. [49:05] Have fun with that. If you enter in the world of I want to write real mojo code [49:09] or native mojo code, [49:12] then you get a very powerful type system. So you can have, you know, at the bottom, [49:15] you have types that can have move constructors, copy constructors, and [49:18] destructors. And so you can write code that manually manages [49:22] resources and do so directly. And that's kind of one of the [49:28] bottom foundational things you can call into C. And so if you want [49:31] to, you can call Malec and free and do stuff like that through [49:34] unsafe hooks. But again, we want people to be able to compose [49:39] together libraries, and we want to do something a safe way. And so what we have [49:43] is we have references, references work very [49:45] similarly to the ones in Rust. Many implementation differences, but you [49:52] can think of it that way. In mojo, it's way less in your face, [49:55] and you don't have to micromanage the borrower checker quite as [49:58] much, but it provides you the same approach and the ability to manage [50:02] references. This is a really powerful thing. And it's a very [50:06] important thing. But again, I don't know if you want to nerd out on [50:10] all the level things, probably not the right thing for the audience. But [50:14] we've learned a lot from Rust. And so Rust is, [50:18] it's wonderful. They paved a lot of roads, and they've done a [50:20] lot of really great work. But there's certain challenges with the [50:22] borrower checker. One example of that is that the way the [50:25] borrower checker works in Rust is that you have the parser, and the [50:30] parser has a bunch of pretty complicated different rules and special [50:34] cases of how it generates CIR. And then you have the borrower [50:37] checker. And the borrower checker comes along and tells you, "Hey, [50:40] did you do it right or not?" And if you did it wrong, then it tells [50:44] you, "Oh, well, you know, maybe in the simple cases, [50:47] it's easy to understand." But in the complicated cases, you're dealing with [50:50] the order of evaluation of how the parser did things that didn't [50:52] do what you meant and all this kind of stuff. [50:55] In mojo, our equivalent is actually a very different thing. [50:58] So we have the same thing where you have a parser and there's a set [51:01] of rules. Our rules are very simple and predictable, [51:03] like I was talking about. We push a lot of complexity out of [51:06] the language and push into the library. But then our borrower [51:10] checker isn't just an enforcer. Our borrower checker decides [51:13] what the lifetime of value is. And so a very big difference between [51:17] Rust and mojo is that in Rust, values are destroyed at the end of a [51:22] scope. And so you can run into issues where you get [51:27] exclusivity violations because something lives too long. And there's various [51:32] solutions to improve this, like non-lexical lifetimes. There's [51:34] a whole bunch of stuff going on in the community to try to [51:36] improve this. In mojo, the way it works is that a value is destroyed [51:39] immediately after its last use. And so it's almost like you have an [51:44] infinitely OCD garbage collector running. And so what this [51:49] means is this means a couple of different things. This means, one, [51:52] it's a much more friendly experience because your lifetime ends and [51:56] therefore exclusivity violations get relaxed [52:00] much earlier, just by default. It's better for memory use. So for [52:04] example, if you're talking to a GPU, it could be that you have a tensor [52:07] and a tensor is holding onto four gigabytes of data. [52:09] And so that's actually a pretty important thing. It's better for [52:12] little things like tail calls and other like core PL things because if [52:18] you have an object on your stack and it gets destroyed [52:20] after your tail call, which is typically how destructors work, [52:24] then you don't actually have a tail call. And so there's all these, [52:28] again, there's this pile of very low level obscure [52:32] details. Rust also has this thing called the drop check flag. And so they [52:37] actually, in the worst case, dynamically track whether or not a [52:41] slot on the stack is live or not because equals in both [52:45] Rust and Swift can either be a reassignment over a value, in which case [52:51] you're doing a mutation, or it can be the first initialization of [52:54] a value. And this matters because you can, in Rust, [52:58] for example, you can transfer out, you can move out a value from [53:01] the slot and stuff like this. And so we solve that problem. And so we [53:07] complete define away categorically. And this leads to a lot [53:09] of simplification language, the program model, you retain the [53:12] safety benefits and other things and the expressivity of references. Okay, [53:16] but are you saying this is calculated at compile time? [53:19] Because at the moment, it sounds a bit like reference counting. [53:21] Yes, yes, it's calculated compile time uses lifetimes. Yep. Okay. [53:26] Yep. The only thing I know about lifetimes in Rust is there [53:29] are pain to use, or at least I've got my head around them. I think [53:34] some people love them. Some people struggle with them. Again, it's [53:38] like many of these things were, you know, I used to work [53:42] with Graydon. And I know that many people in the Rust community, Rust [53:45] has been built on top of the LVM forever. And so I know the community [53:47] is for a long, long time and have a lot of respect for it. [53:50] But also like Rust is 14 years old ish, right? And it's roughly the [53:56] same age as Swift. And so, like we've learned a lot from that [53:59] journey. And it's not dead or anything. Like obviously, [54:02] Rust is a wonderful language with an amazing community. But [54:05] what Mojo represents is an opportunity to take the learning and do [54:08] something that's the next step. And there's a bunch of ways to simplify [54:12] it. Yeah, Rust is groundbreaking in that sense. [54:13] Absolutely. It's inevitable you'll learn things from that. [54:16] Yeah. And so what we're doing is we're saying, okay, cool, let's take that [54:20] forward. As with Swift, learned and made many mistakes in Swift [54:24] and many other systems as well. And so, yes, we're pulling that forward. There's [54:28] a whole bunch of cool stuff in there. So Mojo [54:32] supports async-await natively because that's obviously [54:34] important for high-performance threaded applications. We don't need [54:38] pinning. And so that's a really big deal, it turns out. [54:43] And it's because all values have identity. And so, again, [54:47] there's these very simple, very fundamental, very low-level nerdy [54:51] tweaks to the way the type system works. That means that, [54:54] in practice, if you have a Rust program, it will be doing tons of [54:59] mem copies. And there's optimizations to get rid of the mem [55:02] copies, and sometimes they work, sometimes they don't. [55:04] But in Mojo, by the way, the whole system composes out, you never get mem copies, [55:09] or never get implicit mem copies because of moves. And so there's [55:13] just a bunch of these very low-level, how the language and compiler [55:16] are implemented kinds of things that work well together. [55:19] Okay. That's making me wonder, you said identity, it's making me wonder if you've [55:23] taken a view on things like immutable data. [55:27] Yeah. Well, so we are still rapidly, like, actively debating some of these [55:32] things. My experience from Swift, so if I recall, [55:37] you said you don't know much about the Swift ecosystem? [55:40] No, no, I left before it happened, really. [55:43] So, I mean, in your infant's spare time, you should check it out. [55:46] It has some cool things. One of the things that we pushed, and [55:51] Swift has, again, it's not like a brand new language, [55:54] but it's a pretty modern language. It was built in last, it [55:57] started in 2010, I think. It pushes forward functional programming. [56:05] And it made the observation that, I'll say some things, I'm sure some of [56:10] your viewers will want to kill me, but, you know, [56:14] functional programmers, who I love, by the way, will say functional [56:17] programming is amazing because you never mutate data, you always get new [56:22] values, and because you get new values, you get composition, you get [56:26] predictability, you get control, you get all these different benefits [56:30] of not having mutation. Now, C++ programmers will flip that around and [56:36] say, yeah, but creating a new value every time you want to insert [56:38] something into a list, creating a new list is [56:41] really bad for the machine, it's very bad for performance, nobody [56:43] could ever build a real system on top of that, like, depending on [56:46] how aggressive they want to get. I feel like I'm about to [56:48] join a bar fight, carry on. Yeah, whether it's friendly thing over [56:52] beers or whatever, at least we're not talking about [56:53] Emacs versus Vim or something like truly controversial. Well, Swift does, it says, [56:59] actually, the thing that you want is exclusive ownership of a [57:02] value, and if you have exclusive ownership of a value, you can get value [57:06] semantics. And value semantics in Swift admit local mutation, [57:11] and so you can have, and Rust has its own take on the same idea, [57:16] but the idea is if you have exclusive access to a value, you can [57:19] mutate it. And so now you can have in Swift, the array, [57:23] the dictionary, the string types are all immutable in the Java [57:28] sense, where it's like, if I have a string, I know that its value [57:31] will never change underneath me. And so it looks very, [57:33] very much like a functional programming idiom. And if I have a [57:36] string, it can't change unless I change it. And if I change it, it's [57:40] cool. It's not going to break anybody else. And through [57:43] the implementation, it never does deep copies or stuff like that [57:48] implicitly. And so there's a bunch of stuff that was developed and works [57:52] really well in the Swift ecosystem that I think will come over [57:54] naturally into the Mojo ecosystem. And we're still working through that. Okay. [57:59] Yeah. Okay. That makes sense to me without getting into a bar [58:02] fight. That's it. But that feels like it'd be hard. [58:05] Again, the goal is bring forward the wonderful things of functional [58:08] programming, composition, locality of reference. You don't have the [58:14] spooky action at a distance thing that... Yeah, that's one of the last things. [58:18] So this is all what I love about the functional programming [58:20] model, but then also bring in place mutation so you get efficiency. [58:24] And so bringing those together is good. Swift has some problems that implicitly [58:27] copies things a million times and stuff like this. [58:29] And so we fixed some of those problems, but you've learned from that. [58:33] But that seems to me like it would... Ensuring you have exclusive [58:39] access to a value seems like it must leak into programmer space in a [58:43] way that will be unfamiliar to Python programmers. [58:47] But recall, this is all opt-in. And so if you want to use fully dynamic stuff, you [58:52] can totally do that. And that's totally fine. And so this is [58:56] one system that can scale because we're not trying to change [59:00] the existing world. What we're trying to do is fill in the missing [59:03] world. And so if you look at a modern... One way to look at modern [59:07] Python is that Python is only half the language. [59:11] You have Python and then you have C. Right. [59:16] Right. If you're building a large scale application in Python, you end up [59:19] having... Or C++ or Rust or something else that goes with Python. And [59:24] so what we're doing is we're keeping the Python, [59:27] at least keeping the syntax, but then replacing the C. [59:31] Oh, right. I see what you're saying. And having one system that can do both. [59:34] And so instead of having a switch from, I have Python and it uses underbar and [59:37] bar add, to I have C and C++ and FFI and bindings and all [59:43] that nonsense, you say, "Okay, well, I have underbar add and it works the same [59:46] way and everything just comes across." [59:49] Right. Right. I'm with you. I'm with you. In that case, there's one [59:52] other... I think there's one other big topic in Mojo we haven't [59:55] touched on at all, which is in contrast to Python. [59:59] And I'm reminded of it because of spooky action at a distance. [60:03] Threads, parallelization. That's where... [60:08] Yeah. So super first class in Mojo. Every modern machine is [60:12] multi-core. So keep going with this question. [60:15] So Python famously has a global interpreter lock. [60:21] Yeah. Meanwhile, the moment you allow threads, [60:24] you get bitten by spooky action at a distance. [60:26] There's something changes under your feed. [60:29] I'm glad to hear Mojo has ways to deal with that. But what is the... [60:34] How do I get into parallelization in Mojo? How do I write a parallel program? [60:39] Yeah. So, I mean, again, it pushes things in libraries. And so you can have... [60:43] We have parallel for loops and stuff like that. And they're just library functions. [60:47] And so you can pass an S and function into parallel for loop. And [60:50] so that's the easiest way. We actually have a very high performance, [60:53] low level threading library. And because today's [60:56] systems are not just like four or eight cores, they're servers with 256 cores. [61:03] Yeah, crazy numbers. Yeah. And it's only [61:04] gonna get more crazy if you go forward a [61:06] year or two or five or 10. Right? It's just gonna be nuts. And so [61:10] this is the world that Mojo has designed for. [61:11] Now, one of the things we haven't built out... We'll see. I'm not [61:15] committing to this. Don't hold me to this. But we haven't built out [61:18] an actor system for Mojo yet. In the case of Swift, we fully did. And [61:24] Swift has a full actor system, which is type safe. [61:27] It is very good for large scale, loosely coupled distributed agents, even [61:32] supported distributed actors, if you're [61:34] familiar with actor systems. I didn't know Swift did that. [61:37] Yep. And so that worked out really well. It builds right on top of [61:41] async-await in a very nice way. And so we may do that. I have no idea. [61:47] Right now we're very focused on the structured compute, [61:51] more supercomputer style, and the numeric side of things. And so I [61:57] suspect we will find ourselves wanting to do an actor system someday, [62:00] but we haven't prioritized that yet. Would you possibly expect someone to do [62:04] it just as a library? Yeah. I mean, so that's also a thing. The [62:09] Scholar World built out Akka, I think, and has done really great [62:13] things. The only downside about that, and so I mean, [62:15] maybe it would be great. And I would prefer it to be in the library if we can, [62:20] is just make sure that it's memory safe. Because Akka, for example, [62:23] is not memory safe, and that leads to certain challenges. But on the [62:27] other hand, it can be very pragmatic to say, well, [62:31] do one step at a time and he'll climb and then get implementation [62:34] experience with libraries. And then if there's a benefit to putting [62:36] something in the compiler to mediate accesses across actors, [62:39] then we can add a little bit of type system support for that [62:42] and then get the bulk of it in the library with a little bit of a [62:45] type system. Right, yeah. A separation of where it should be. [62:49] Okay, so my options then for parallelizing and Mojo broadly, you said [62:53] I've got async await, I can create a thread to run on, and [62:57] you've got certain parallelized primitives. [62:59] Yep. Yep. Yep. And if you want to, you can call arbitrary C code [63:02] and you can go completely nuts and do whatever you want to do. Right. [63:05] And so, but we're encouraging people to not have to do that. [63:09] It's very nice to just say, do this thing in parallel. Again, [63:13] it's still imperative code, but it feels more declarative. And I [63:16] think that's again, we're raising abstraction levels so that [63:19] people get out of the muck a little bit. Okay, that gives me plenty of [63:22] parallelization things to play with. The question is, it comes [63:27] up again, as soon as you're doing anything fancy with CPUs, [63:31] that different CPUs support different things and sticking a [63:34] threading model on a single core is going to be different to 256 cores. So [63:41] what, how much does CPU architecture matter [63:45] to a Mojo programmer? How much does it leak in? How much control do I have? [63:50] Yeah, well, so I think there's a couple of different things. There's how much [63:53] do you have to care about? And then there's how much do you get [63:56] to care about if you want to? Yeah. And so, generally, you know, my [64:00] view is that there's a huge range of different kinds [64:03] of programmers they have different care abouts. And so most [64:05] programmers just want to say, here's a parallel for loop, go nuts, then [64:10] you're fine. And so there from the systems level, [64:12] you want to be able to support structured nested parallelism, you [64:15] need, you need thread libraries to compose, you need like async await, so [64:19] you're not getting bogged down with tens of thousands [64:23] or hundreds of thousands of threads that then kill your machine [64:25] stuff like this. But I think that's pretty simple. The cool thing is [64:29] when you start getting into more complicated accelerators [64:32] and things like this. And so if you think about CPUs have 256 [64:36] cores, GPUs have thousands of cores or thousands of threads. Yeah, [64:41] right. And so, and the programming model around a GPU is [64:44] extremely different than the traditional CPU programming model. [64:48] And so one of our goals is to make it so people can write much more [64:52] portable algorithms and applications. And coming back to [64:57] this two level idea, the graph level is pretty easy. I mean, it's [65:00] actually really hard, but it's easy to understand how you make a graph [65:04] portable. Yeah, you implement the graph for one thing, [65:08] you implement the graph for another thing. And so you can have [65:10] two different stacks that are optimized or designed for the [65:14] different kinds of hardware. And the power of being declarative [65:18] is that you're separating out a lot of the implementation [65:20] concerns, which makes that possible. But then if you get down into writing for [65:25] loops, right for loops are different, right for loops [65:28] are imperative code, imperative code is inherent, it is kind of the [65:31] bottom of the stack. And so what we've what we've done is we've carved out [65:36] the ability for people to define their own abstractions [65:39] in mojo. And then just like we were talking about with complex numbers [65:43] before, you can have complex number, it's a very simple [65:47] abstraction, but it's an abstraction, you can go put a hack in [65:49] that is target specific. When you start talking about accelerators, [65:54] really what ends up mattering a lot is both parallelism, but then also [65:59] memory. And so how you use the memory hierarchy is the [66:03] most important thing these days, particularly for GPUs and LLMs in this [66:08] world that we inhabit. And so modern GPUs and CPUs have many level [66:14] memory hierarchies. And so, you know, the way to think [66:16] about a CPU is you've got a big vector register file, and that's [66:20] kind of like your l zero cache, it's like your registers, right? And then [66:24] you have an l one cache, which is really fast and [66:25] close to the CPU and l two cache, l two caches, sometimes shared [66:29] with one or two cores, they have an l three cache and shared with all of [66:32] the cores, and then you have main memory and you go out and [66:34] the GPU has roughly the same idea, the details very different, but [66:38] it's roughly the same idea. And so if you're writing something like a [66:41] matrix multiplication, inherent to getting high [66:44] performance with matrix multiplication is not just doing a dot product, either way, [66:49] you have to process the workload and tiles. And so what we've seen is we've [66:55] seen an emergence of various tile based programming models, [66:59] where instead of encouraging developers to think about [67:02] things, literally a for loop doing a load in the store and an add [67:05] and a multiply, instead, you're thinking about processing a tile [67:09] at a time, what you do is you write the algorithm for a tile, [67:13] and then you use higher level orchestration logic that [67:16] then says, okay, on this device, I'll traverse this way, or I will [67:19] prefetch the data in two steps ahead, or I will do, [67:23] you know, I will get better reuse if I go vertically and horizontally or whatever, [67:27] whatever it is, there's all these tricks that the world has developed. [67:31] Right. When we say tile, am I imagining, because we're talking [67:36] about GPUs, am I imagining like something that's eventually going to be [67:39] printed as a square on the map in my game? [67:43] I'm thinking, yeah, so if you're thinking about textures, so yeah, so [67:47] texture is a two dimensional rectangle of data. But so to to, so so if [67:55] you think about a texture map, so two dimensional rectangle, [67:59] in AI, you get a generalization of that called a tensor. And so you [68:03] take a two dimensional group of numbers, and you make it an n [68:05] dimensional group of numbers, right? It's the same idea. Okay. But now [68:09] just just put that just put this in your brain. I know you don't think [68:15] about this every day. And so to me, it's fun to just kind of dive into [68:19] this stuff. You talk about a two dimensional array [68:21] of data, even in the simple case, what really happens is it [68:24] gets linearized in memory. Yes, that doesn't surprise me. [68:29] And so when you go down a row, so if you go over, if you go over one, [68:33] you just add one to the pointer into the next error, next place in [68:36] memory. But if you go down a row, you're adding a whole roll [68:39] rose worth of data over and so you're jumping. Yeah. And so and [68:43] so for a computer, it's very easy to access things that are very [68:48] local. And if you start striding, right, it's very, it's a lot [68:53] less efficient. Okay, and when that gets into multi dimensional [68:56] vectors, that becomes pronounced. Exactly. And so now when you do things [69:02] like matrix multiplication, this the shape of a matrix [69:04] multiplication, consider two dimensional matrix and two dimensional [69:07] matrix is typically you're going horizontally through the row of one [69:11] matrix, and you're going vertically through the row of [69:13] another matrix to compute an output element. And if you could [69:17] tell the GPU to arrange those two matrices differently. Yep. For [69:24] example, you transpose it ahead of time, things could be a lot [69:27] more efficient. If you process instead of processing one row and [69:31] one column at a time, you can process two rows and one column. [69:36] And then what that means is when you're processing [69:38] column, you're accessing two elements next to each other, for example. And so [69:42] as you generalize this out, you get this idea of a tile. And so [69:48] you get this logical concept of I'm processing, for example, [69:53] a two dimensional block of memory. And I'm doing this and I'm [69:56] composing against other things. Turns out modern modern hardware, not [70:02] only is it complicated and vector and parallel and like all [70:06] these other complexities we've been talking about, but they're now adding [70:10] full on matrix operations to the silicon. And so you can literally [70:14] do a matrix multiplication of a very small matrix [70:16] typically, you know, like a four by four or a 16 by 16. Some [70:21] accelerators, you can do 120 by 128. Boom, big operations. The intuition here [70:27] is that AI is important to the world and silicon is [70:30] fundamentally two dimensional. And so if you use the two dimensional [70:34] nature of silicon to put down a matrix multiplication, you can get a [70:37] lot of performance and energy and other benefits from [70:40] that. And so a lot of the challenge in this world is how do I use these [70:45] accelerators? How do I map these things and these tiles onto these [70:48] onto these devices? How do I use the memory hierarchy [70:51] efficiently? And like, and this becomes as important as the [70:54] numerics because the performance difference can be 10x or 100x depending [70:58] on what's going on. It's quite a big deal. And so [71:03] if you go through the last 10, 15, 20 years, like HPC has been dealing with a [71:08] lot of these problems for many years. And, you know, we have [71:11] the Fortran world, we have various C++ template libraries, [71:15] we have a whole bunch of stuff that was developed and built to try to [71:17] combat some of these problems. And they came up with fairly, I mean, [71:21] sometimes very powerful, but fairly niche solutions. And the [71:24] usability was never very great. And so this is where if you pull [71:28] together Mojo's ability to talk to all these crazy hardware features like [71:33] the matrix multiplication operations, build higher [71:37] order combinators so that you can build libraries so that you can [71:41] write the tile algorithm and not the orchestration logic because you don't [71:45] want to know how that stuff works. You only want to know [71:47] how part of it works. And then the compile time meta programming, that [71:52] enables you to write really reusable and portable code. And so one of [71:55] the things I recently gave a talk at the NVIDIA GTC [71:59] conference, which is their big technical conference, and talked about [72:03] how this all composes together to make it so you can write high [72:05] performance numerics for the same algorithm works on GPUs [72:08] and CPUs. Right. Yeah. And that's pretty cool, right? And it's not [72:13] just about today thing of software, a GPU and CPU. It's about if [72:18] you're making a major investment in building software, [72:21] and that's how software works, like you want your software [72:23] investment to last for 10 years or 20 years, you want the amount, a certain [72:28] amount of being able to adapt to the needs of new hardware. [72:31] Yeah, and hardware will continue to evolve. It's moving faster [72:33] than ever. And so what we're doing with Mojo is helping break through some [72:36] of these boundaries that have prevented people from [72:39] building portable software and while still being able to utilize high [72:43] performance, super fancy features that people are coming out with. [72:46] Okay, so how is this going to work in practice? Let's say [72:50] I've written some code, which is fairly fast. We're wearing my Python hat, I've [72:55] written some in Mojo. NVIDIA comes along with a new GPU with [73:00] this great new CPU instruction. I wait, I'm assuming [73:04] what happened is I wait for MLIR to support that CPU instruction. And then I [73:10] just pass along to my Mojo library and write that. Yeah, so [73:14] NVIDIA is a great citizen in the software world because [73:18] every time they come out with some new chip, and one becomes [73:21] available, they provide LLVM access to their stuff generally. And so we can [73:25] talk directly into that stack. And generally hardware [73:28] makers are very LLVM friendly these days, which is really cool. It [73:32] helps enable innovation. So Mojo can talk to MLIR and talk to LLVM [73:36] and get direct access to all this stuff. Okay, [73:39] just cool. This sounds like... And also, let me zoom back out and say, [73:44] you know, this is deep nervery. This is something that a very small number of [73:48] very important people care about. Most people will build on top [73:51] of higher level libraries. And so we have like the [73:53] Max Engine, for example, which gives you just give me a graph. I don't want to [73:57] know how any of that stuff works. Here's just a graph, go to [74:00] town, right? Or other people say, hey, I just got some [74:03] Python code, Python code slow. I'll put in some types. Now it goes [74:07] 100x or 1000x faster. And I'm not even doing fancy accelerator stuff. [74:12] I'm just running on CPU. But 100x or 1000x is pretty [74:16] material for, you know, I have a big investment in Python code, and I want to [74:19] make it faster. And I don't want to like retrain all my [74:21] engineers. And so that's why that's cool. Even if you don't go [74:25] all the way down to the full craziness of what the system can do. [74:29] Yeah. Where I'm sitting, I don't want to write like GPU level code. [74:35] I just want my code to be fast. But when I find out that it's not [74:38] fast, I want to be able to do that without someone telling [74:41] me, oh, you picked the wrong language. That's exactly right. And [74:45] I mean, this comes back to you. You're asking why pick Python as a [74:48] Pythonic language, right? One of my one of the things I've [74:51] learned is that programmers, let me stereotype all of us. Let me make a [75:00] sweeping generalization that's obviously doomed to fail. [75:03] Programmers are busy people, they have things going on. They're [75:06] not most people are not going to be just like learning a new thing [75:12] for the heck of it right now. Obviously, there's exceptions, there's [75:15] researchers, there's other people that just love learning and [75:17] are passionate about things. But most people are busy. And so learning new [75:22] things is not something people generally have the time to [75:28] dedicate a week or a month to do. On the other hand, if you meet [75:32] people where they are, you provide something familiar so they [75:35] don't have to retrain from scratch to get up to a baseline. And you [75:38] give them new tools. Programmers I've seen generally love [75:42] growing. And so learning a new thing, here's a new trick. I saw that with Swift [75:48] when Swift launched, we said to the Objective-C world, hey, [75:51] you're all familiar with classes, classes are great, [75:53] they still work in Swift. Here's a new thing called a struct. It's got these [75:57] different tradeoffs, it's way more efficient, it doesn't use [76:00] dynamic dispatch or whatever. And people and or here's [76:04] algebraic data types, enums, right? Wow, you have a payload around [76:07] your new pattern matching. Like this was a huge aha moment for [76:12] folks. And people loved being able to learn incrementally [76:16] from the base that they were on. And so what Mojo is really about is about [76:20] meeting people where they are and then allowing them to grow [76:22] in situ instead of saying you have to go off to the mountain [76:25] and retrain and boot camp for a month. And then you can be [76:29] basically effective in a new world. And so I think that's why people are [76:33] excited about what's going on with Mojo. Yeah, I can see that. I always think the [76:37] main reason I don't want to learn new things is [76:39] I'm busy learning other new things. You can't get to the top [76:43] of my stack so easily. Yeah, well, I mean, it's a busy world out [76:46] there and there's a lot going on. Yeah. But okay, so I actually do have [76:50] some Python code at the moment. If I thought, [76:54] okay, well, let's give this a try and rewrite it in Mojo. What's [76:57] my experience going to be like today? How mature is it? What's coming on [77:02] the roadmap? Where are you going with this? [77:04] Cool. Yeah. So Mojo is still a relatively young language. It's [77:07] useful. It just launched last May. So it's been public for less than a year. [77:14] But it's doing really well. I think we have over [77:16] 175,000 people that have used Mojo. We have a nice Discord [77:22] community that has over 22,000 people hanging out and all the magicians like [77:27] talking to each other, doing cool stuff. We have cool demos. [77:31] You've got the cute nickname too. That's a very important step. [77:36] Oh, I forgot the most important thing about Mojo, by the way. [77:39] The most innovative thing is that we support an emoji file [77:43] extension in addition to .Mojo. So that also causes [77:47] people's heads to explode. And so, innovation of all sorts. But the [77:54] community is doing really well. It's very exciting. Actually, as we [77:57] record today, we're open sourcing a big chunk of Mojo. [78:00] And so the entire standard library, which as we were just talking [78:02] about is the heart and soul of the language is all open sourcing. And so [78:06] we've been on a quest to open source more and more and [78:09] more of the stack over time. And so that's a really big deal. I [78:13] know that we've been public about this and telling people about it [78:15] for a while, but I know people are waiting for this [78:17] for a long time. And so what we're seeing is we're just seeing just [78:20] a continued growth of the community and continued passion projects, [78:24] cool things going on. And I think this will be a huge [78:26] step. And one of the things that's very important to me is we talked [78:30] about, so I've built the LVM community from scratch from my research [78:34] project at the university. I built the Swift open source [78:36] community and worked in many, many, many other communities. And [78:40] what I've seen is that open source isn't just about having code on [78:44] GitHub. Open source is about having an open community, [78:48] having an inclusive way of developing code together, working [78:53] together with a common goal. And so we put a lot of energy into not [78:58] just providing source code, but also getting a [79:00] contribution model, picking the Apache two license and things like [79:03] this so that people have patent coverage and like all the things that [79:06] follow best practices. And so I'm really excited about that. [79:09] I think that people are going to have a lot of fun and I look [79:11] forward to being much more open with our development of Mojo. Okay, [79:15] that's cool. So if I do decide to do this, I'm going to be able [79:18] to find lots of people to answer my dumb questions on Discord. Yeah, [79:23] yeah, yeah. Please join our Discord. That's a great place to go. And [79:26] there's a whole bunch of everything from folks that are [79:28] just interested in type theory, nerdery to AI stuff, to I want a [79:34] better Python, to like, there's many different angles. And again, [79:38] the cool thing about Mojo is that it is being built and it has to be state of the [79:43] art to solve these pretty hardcore, pretty gnarly problems at the frontier of [79:49] computer architecture and programming languages. [79:52] But we're building in a way that it's completely general. And so [79:56] we're focused on AI. And there's a lot of pain and suffering in the world [79:59] of AI that we hope we're helping to alleviate. But [80:02] it turns out that, you know, a lot of people write web servers and a lot of [80:05] people do other things. And so it's fantastic to see people [80:09] building into that space, even though we personally can't, [80:12] don't have the expertise to invest in that. Yeah, well, that's what the [80:14] language is supposed to do, right? Enable other programs. Yeah, yeah. [80:18] That's exactly right. So concretely, then, if I go and install [80:21] Mojo and take my existing web server writing knowledge, [80:26] am I going to be able to do like the equivalent of pip install the existing [80:32] web server library that I like from Python world? Yeah, you can [80:35] totally import and use it and it will just work. Literally, [80:38] you don't have to write wrappers or anything, just import it [80:41] and go. That would just work. The one problem is that if you take the [80:46] Python source code and you move it to a .Mojo file, [80:49] you'll have to make changes right now. And the number one missing [80:52] feature that we have right now is classes, which is a pretty big deal in [80:57] Python. And so we have very strong structs and we have [80:59] very strong static features. We have references and all these [81:02] kinds of things. And so, again, what Mojo has built out is all the [81:08] C++ and Rust equivalent features. And even then, [81:11] there's some minor things you're missing, but that's its strength. [81:14] And so if you come at it from a systems programming world today, [81:19] then I think you'll be very comfortable. If you [81:21] come back in six months, then we'll have classes and we'll have [81:24] other things built in. And then you'll be more [81:27] comfortable as a Python programmer. Okay, I'm going to go and check it out [81:31] and see how comfortable it makes me today. [81:34] Very good. Great. [81:35] Yeah. So, but it's very fun. And so, I mean, I [81:37] love this. I mean, obviously, I love this stuff. This is [81:40] a passion of mine for years, but I love the community side of [81:45] it. And the thing I love about Swift, for example, is I still get [81:47] people that stop me in the street and say, "Wow, [81:50] I recognize you. Thank you for helping drive this thing and make [81:53] this happen." Because of you, I learned how to get into programming and [81:56] Objective-C was always too scary and things like [81:58] this. And so with Mojo, what I hope happens, and these things take a couple [82:03] of years to play out, but what I hope happens is we get all [82:06] these people that know Python and they don't consider themselves [82:09] to be real coders or something, but they know Python and they can [82:15] continue to grow, right? Because they're not faced with, "Are you [82:19] a Python programmer or a C++ programmer?" Or whatever they [82:23] think is a Rust programmer, like this scary other threshold. And if we can get [82:29] more people involved, be more inclusive to good ideas, right? [82:32] What I think is we'll find computer science and [82:34] these technologies can go even further and have bigger impact [82:37] than they've had so far. And I love that, right? And I am a true [82:41] believer in developers. By the way, huge fan of your show. And so... [82:46] I did not pay Chris to say that. That's what I love. [82:49] Yeah. Well, I really hope it succeeds because [82:52] anything that brings new ideas to programmers and helps [82:55] unify our somewhat fragmented view of programming, I'm all for it. [83:00] Yep. Cool. Yep. [83:01] Chris Latner, thank you very much for joining me. [83:04] Yeah. Well, thank you for having me, Chris. [83:06] It's great to be here. Cheers. See you again. [83:08] Thank you, Chris. And I have to pick up on that last point. It [83:12] makes me sad to think that there might be Python programmers out there who [83:16] don't think they're real programmers. Of course you are. You absolutely are. If [83:20] you were in the business of teaching computers to [83:23] do things they couldn't do before, you're a real programmer. Don't [83:27] let anyone tell you different. And if you're in the business of learning [83:30] how to do that better and exploring new ways of doing it, [83:34] then you're a friend of mine too. As usual, you'll find links to all we've [83:38] discussed in the show notes. Check it out if you want to take a [83:41] look at Mojo, if you want to kick the tires on it. [83:43] I've been having a play and having some fun early days, but very, very promising. [83:49] Before you go and do that, do take a [83:51] moment to click like or share or rate or subscribe, [83:55] because I'd love the feedback. Of course I would. And the [83:58] algorithm would love to let other like-minded people [84:01] know that you've enjoyed this. And that means you and I and future [84:04] listeners will get together more easily. Until that time, when there's a future [84:09] episode, I think it's time for me to say goodbye. [84:12] I've been your host, Kris Jenkins. This has been Developer [84:14] Voices with Chris Latner. Thanks for listening.