Mojo SDK v0.7 is the first big release of Mojoš„ in 2024, and itās chock full of new language and standard library feature goodness. In this blog post, Iāll share some of the key highlights from this release with examples, and discuss what they are and when to use them. Iām only going to cover the new features, for a complete list of whatās new, whatās changed, whatās removed, and whatās fixed in this release, be sure to check out the changelog in the Mojo documentation.
First things first: Update your modular CLI and Mojoš„ SDK Before we take a closer look at the new features, make sure you update the modular CLI and mojo. First, head over to the developer console and follow the platform-specific instructions to upgrade your modular CLI to version 0.4.1. The latest version of the modular CLI includes performance improvements and a brand-new progress bar!
Once youāve updated your modular CLI, run modular update mojo to get the latest v0.7 release of Mojo SDK.
Whatās New in Mojo SDK v0.7? This release includes exciting new features across the core language, the standard library, and developer tools. Iāll highlight the key features in this release categorized into two areas:
Mojo language and standard library features Mojo CLI and language server features New Mojo language and standard library features Mojo-native dictionary type This release introduces a new Mojo-native dictionary type! Dictionaries are really useful dynamic and mutable data structures for storing key-value data. If you are a Python data science developer, youāve probably used dictionaries to store model configurations, model architectures, hyperparameters or to read entire JSON files. Letās take a look at the Mojo dictionary type with a simple example.
Mojo
from collections.dict import Dict, KeyElement
@value
struct StringKey(KeyElement):
var s: String
fn __init__(inout self, owned s: String):
self.s = s ^
fn __init__(inout self, s: StringLiteral):
self.s = String(s)
fn __hash__(self) -> Int:
return hash(self.s)
fn __eq__(self, other: Self) -> Bool:
return self.s == other.s
fn main() raises:
var hyperparam = Dict[StringKey, Float64]()
hyperparam["learning_rate"] = 0.01
hyperparam["weight_decay"] = 1e-6
hyperparam["momentum"] = 0.90
print('Dict size: ',len(hyperparam))
print('Learning rate: ',hyperparam["learning_rate"])
print('Momentum: ', hyperparam["momentum"])
print(hyperparam.pop("momentum"))
print(len(hyperparam))
Copy
In the above code example, we created a simple Mojo dictionary called hyperparam to store a modelās hyperparameters learning_rate , weight_decay , and momentum as key-value pairs. You can query an element just like how youād do it with Python, by calling dict_variable[ākey_nameā] . To remove an element from the dictionary, use the pop function.
If you pay close attention to the dictionary creation code, youāll see that we use StringKey and not the standard library String type. Dictionary keys need to conform to the new KeyElement trait, which is not yet implemented by other standard library types like String in this release. They will be implemented in a future release, but for now, youāll need to create custom wrappers around the value type that implements the KeyElement trait.
New functions to get host CPUās physical, logical and performance core counts If you want to write portable parallelizable code, itās useful to be able to programmatically access the number of cores on the host CPU. However, modern CPUs may implement a hybrid performance+efficiency core CPU architecture or include logical cores, and choosing the wrong number of threads in code may hurt your parallel applicationās performance. In this release, sys.info includes 3 new functions that let you programmatically access the number of physical cores, number of logical cores and, number of high-performance cores.
Mojo
from sys.info import num_physical_cores, num_logical_cores, num_performance_cores
fn main():
print('Number of physical cores:',num_physical_cores())
print('Number of logical cores:',num_logical_cores())
print('Number of performance cores:', num_performance_cores())
Copy
On My Apple MacBook Pro M2 Max system running the above code shows that I have 8 performance cores even though I have 12 physical cores.
Output
Number of physical cores: 12
Number of logical cores: 12
Number of performance cores: 8
Copy
On an Amazon EC2 c6i.4xlarge instance, see that although there are no efficiency cores, it does support logical cores with Intelās Hyper-ThreadingĀ
Output
Number of physical cores: 8
Number of logical cores: 16
Number of performance cores: 8
Copy
New safe References type (prototype) In this release, Mojo also introduces a prototype version of a Reference, a safe alternative to unsafe pointers. References have the same in-memory representation as Mojo pointers but also track a ālifetimeā value so the compiler can reason about a potentially accessed set of values. While this is a major step forward for the lifetimes system in Mojo, it is a very early prototype implementation. Read more about references in the changelog and the Reference documentation .
New Mojo CLI and language server features New compiler option to opt-in debug assertions used in standard library functions Mojo standard library functions include several assertions to catch various errors but are not enabled by default to improve performance. Letās take a look at a simple example.
Mojo
from sys.info import simdwidthof, simdbitwidth
alias simd_width: Int = simdwidthof[DType.float32]()
fn main():
print("SIMD Width:",simd_width)
let a = SIMD[DType.float32](1,2,3,4,5,6)
print(a)
Copy
If you compile and run this code, youāll see the following output:
Output
mojo mojo_stdlib_assert.mojo
SIMD Width: 4
[1.0, 2.0, 3.0, 4.0]
Copy
Everything looks good, and it works as expected. If you look closely at the code, we initialized the SIMD type with 6 values, but the SIMD width for Float32 is only 4 . But SIMD did the right thing and truncated values > 4 . The SIMD implementation in the standard library includes a check to see if the number of input values is larger than the SIMD width, but since these assertions are disabled by default, you only see a truncated output. To enable the assertions, you can now opt-in by specifying -D MOJO_ENABLE_ASSERTIONS when calling the mojo compiler.
If you compile and run this code with the flag, you get an Assert Error and the stack trace. This new feature be useful for debugging if youāre seeing unexpected results.
Bash
mojo -D MOJO_ENABLE_ASSERTIONS mojo_stdlib_assert.mojo
SIMD Width: 4
Assert Error: mismatch in the number of elements
Please submit a bug report to https://github.com/modularml/mojo/issues and include the crash backtrace along with all the relevant source codes.
Stack dump:
0. Program arguments: mojo -D MOJO_ENABLE_ASSERTIONS mojo_stdlib_assert.mojo
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 mojo 0x0000000100c9a65c llvm_strlcpy + 52684
1 mojo 0x0000000100c987bc llvm_strlcpy + 44844
2 mojo 0x0000000100c9acfc llvm_strlcpy + 54380
3 libsystem_platform.dylib 0x0000000188af5a24 _sigtramp + 56
4 libsystem_platform.dylib 0xffff80028000428c _sigtramp + 18446603340370471072
5 mojo 0x0000000101070728 llvm_strlcpy + 4075160
6 mojo 0x0000000100bf2cf0
7 mojo 0x0000000100bdd114
8 dyld 0x00000001887450e0 start + 2360
[51137:14139255:20240125,031201.678546:WARNING in_range_cast.h:38] value -634136515 out of range
[51137:14139255:20240125,031201.682782:WARNING crash_report_exception_handler.cc:257] UniversalExceptionRaise: (os/kern) failure (5)
Trace/BPT trap: 5
Copy
New Find All References and Go to References feature support in Visual Studio Code IDE We discussed some exciting new features in the core language and standard library, but weāre not done yet. The Mojo Language Server also gets new superpowers! The language server now implements the References request. IDEs like Visual Studio Code can use this to provide support for Go to References and Find All References . Currently, references are limited to a single open document, cross-document references will be supported in a future release.
But wait, there is more! We discussed key highlights in this release, but thereās more! This release also includes changes and enhancements to closures, unroll, vectorize and a host of bug fixes. Check out the changelog for a full list of whatās new, whatās changed, and bug fixes in this release:
Download Mojo SDK v0.7 today! Here are other useful getting started and community resources:
Until next time! š„