The augmented reality design needed some code written, the shapes of the optical surfaces need to be calculated. It is not a large amount of calculation but I do have an upcoming optics topic which does do some heavy wavefront calculations, so I thought I would invest some time in using Modular's Mojo which is getting a lot of buzz as the best way to slice and dice on a computer. Widely described as a superset of Python with amazing compiler optimization. The next big thing, and capable of using a GPU or a CPU or both.
Sounds great! Start with an easy project, get settled in before I need to the the all to all wavefront calculations for that future blog topic.
Well I got a reality check and will be a few days late with this week’s blog. Mojo is not quite the next generation of Python that the talk would seem to say. Not yet, anyway.
A Domain Specific Language
DSLs are things you can do in some modern languages, where you write code that provides some new syntax that matches a special area of work - a domain - with a syntax that is expressive and natural. For example, maybe you could have a DSL that allows you to write algebra just like you see it in textbooks, or you could write chemical dynamics calculations using chemical formulas.
Well, that is what Mojo is, at least at the moment. With the special twist that it is allowing you to specify all the things about your code that an optimizing compiler needs to know. Instead of writing in a higher level of abstraction than Python, it allows you to specify, abstractly, lower levels of detail - in a very well thought out way - in the middle of what is otherwise easy-going and approachable Python code.
If you were expecting this to be easier and higher level than Python, no.
This is good if you are doing AI
I’m pretty sure this makes sense for your advanced AI programmer who wants a portable, easy way to write high level code that will compile to monster performance while having access to most of the conveniences of Python. Which is what Modular said their goal was - they were working on their MLIR code generator and needed a programming environment to use for driving it. Python is already used for AI modelling - PyTorch and TensorFlow both use Python to orchestrate things - and so adding Mojo to Python was a good choice. It allows you to write code embedded in your Python, where the code looks like Python, but compiles down to high performance tensors that can flexibly compile to various AI chips or systems. Most current systems work with MLIR even if they do not adopt Mojo, so there is a lot of good work accumulating in that ecosystem.
In other words, it is designed to be great as an AI implementation language that just happens to borrow Python for all the incidental support. It is not designed to change the way Python does Python - indeed, you might find it most effective just to use the %%python mechanism to drop into pure Python whenever you are not working on the big arithmetic parts.
It is not Next Generation Python
As a DSL, Mojo is in someways the opposite of normal. Most DSLs abstract you further from the hardware and the code generation. What Mojo does is allow you to write code that precisely specifies various low-level behavior of your data types, so that the compiler can safely optimize it for different hardware. This is a high-level abstraction only if your domain of interest is how to make vectors and tensors calculate faster. Mojo is not general abstraction and programming productivity. Indeed, at a first glance it looks like someone took Rust or C++ functionality and translated it into Python syntax, along with a bunch of compiler intrinsics that you will want to decorate your data structures with. It sits inside the Python peacefully but it does not look the same as other Python.
The Mojo data structures are a little weird too. I happily created a bunch of structs for things I needed in my optics work, only to discover that they really were not much use in Mojo. The Mojo collections only work with primitive data types - ints, floats, pointers - and you quickly get totally inscrutable piles of error code from the Mojo compiler when you attempt to use structs in ways that, in Python, would be quite natural. So it was a little tedious to have to decorate the new structs with all sorts of compiler intrinsics that Python does not need, but then a real punch to find out these were not useful combined with other Mojo features.
Mojo is a really common word
At least, not useful in ways I’ve been able to find. I assume that Modular is going to improve the utility of structs over time but for now they have more AI-oriented work items and structs feel half-finished.
An additional problem is that the documentation is sparse and Mojo is a really common word. Web searches for something like list or connection in Mojo are just swamped by irrelevant topics. There are even a few completely unrelated programming projects out there with Mojo in their name. Since Modular Mojo is recent, there is not a large body of knowledge providing support and help from the community, or if there is, the search engines are not tuned to find it. This is quite different from looking up Python topics.
You can search with adding “ site:modular.com” to exclude unrelated results, but that is not much better. Modular provides almost no sample code. Their library manual lacks the usage examples which are common practice elsewhere in class library documention and the various modules are described in inconsistent styles, often cryptic. Clearly a work in progress. It probably makes sense combined with reading the source code, which is sensible if that is you level of investment in it. But if you are a typical Python user, which means you are accustomed to the world’s most usable programming environment with tons of support options, this is a cold shower.
What to do
So, my relatively simple project hit a wall, and is thus slightly delayed. I have two options for progress: one is to keep using Mojo but rewrite it with arrays of numeric data types and only use the structs where there may be clarity and convenience. I would still see what the code generation advantages are, and I could probably still adapt this style for the wavefront work.
My other option is to use Julia, which is a Python-inspired next generation language that also compiles efficiently. It is a joy to use with modern and intuitive features that expand your imagination of how to program. When Mojo was announced there was a lot of angst in the Julia community about whether Mojo was going to replace them: at least for the present the reality is that Mojo is not in the same space as Julia.
Mojo will likely win dominance in AI space and might eventually grow to be more polished and useful in other engineering and scientific spaces - but Julia is looking at using MLIR as well, so the performance competition will be interesting to see.
I will probably do a bit of both: see what the Mojo code looks like after reorganizing to back out of using structs, and see how well Julia runs these days on matching the computation benchmarks that Mojo provides, on my same machine.
Next week
I will have made a decision by Monday, when I will write a short post about it.
My next installment of the augmented reality optics should come out on Thursday, the 18th. Thank you to all my readers! As always, comments are welcomed.