I’m sure many of you are familiar, but there’s a treacherous gap between finding (or building) a model that works in PyTorch, and getting that deployed into your application, especially in consumer-facing applications.
I’ve been very interested in solving this problem with a great developer experience. Over time, I gradually realized that the highest-impact thing to have was a way to go from existing Python code to a self-contained native binary—in other words, a Python compiler.
I was already pretty familiar with a successful attempt: when Apple introduced armv8 on the iPhone 5s, they quickly mandated 64-bit support for all apps. Unity—where I had been programming since I was 11—kinda got f*cked because they used Mono to run developers’ C# code, and Mono didn’t support 64-bit ARM. Unity ended up building IL2CPP, which transpiles the C# intermediate language into C++, then cross-compiles it. Till date, this is perhaps the most amazing technical feat Unity has achieved imo.
I set out to build something similar, but this time starting from Python. It’s a pretty difficult problem, given the dynamic nature of the language. The key unlock was the PyTorch 2.0 release, where they pioneered the use of symbolic tracing to power `torch.compile`. In a nutshell, they register a callback with the Python interpreter (using CPython’s frame evaluation API), run a function with fake inputs, and record an IR graph of everything that happened in the function.
Once you have an IR graph, you can lower it to C++/Rust code, operation-by-operation, by propagating type information throughout the program (see the blog post for an example). And now is the perfect time to have this infrastructure, because LLMs can do all the hard work of writing and validating the required operations in native code.
Anyway, I wanted to share the proof-of-concept and gather feedback. Using Function is pretty simple, just decorate a module-level function with `@compile` then use the CLI to compile it: `fxn compile module.py` .
TL;DR: Get Rust performance without having to learn Rust ;)
Am I missing something or has that been possible for at least 20 years?