Difference between Float32 and DType.float32
I don’t have a ton of experience with python or AI/ML and so trying to figure out this basic questions in the comments around the difference / similarity between Float32 and DType.float32 more context in this snippet:
5 Replies
TL;DR:
DType
describes a data format in the abstract. Types like DTypePointer
, SIMD
, and Buffer
use DTypes to describe the data they store. Float32
is a concrete type which you can instantiate.
These aren't really related to AI/ML or Python.Float32
is a type. You can instantiate a Float32
, like you did in your code (Float32(i)
). DType
is a structure that provides various utilities for working with data types, including enumerated values (enums) describing various data types, like float32
. So DType.float32
is a value that describes a type.
It's used in a variety of generic types like DTypePointer
and SIMD
to describe the type of data being stored. You can't create a DType.float32, but you can create a Float32
(which is a scalar value of that dtype) or a Buffer
or SIMD
vector made up of DType.float32
values.
I'm going to take a short tangent here. I swear it's related. I don't know if you've touched on SIMD
yet--it's another type that tends to confuse folks, and this part is kind of related to AI/ML. SIMD (single instruction, multiple data) is a technique for parallelizing data operations when you want to do a lot of similar operations. A Mojo SIMD
type is a small, fixed-sized vector--or array--of numeric data types. These are used heavily in low-level AI/ML programming, so they're built right in to the Mojo standard library. A SIMD[DType.float32, 8]
is a vector of 8 Float32
values. You can do something fancy like take the square root of all of the values with a single operation:
With SIMD, doing 8 operations at once takes about the same time as doing one—so you can see why this is desirable when you're crunching a lot of numbers.
OK, so I told you this was related, and it is. What exactly is that Float32
type. you're using? It's actually an alias for SIMD[DType.float32, 1]
. That's right, it's a SIMD vector holding one 32-bit floating point number.
When you create a DTypePointer[DType.float32]
, it's basically the same as creating pointer to an array of Float32
scalar values.@Arthur Evans following up on the question, as I understadn Float32 is a type defined in the standard library.
is Dtype.float32 is also part of the standard library or it is implemented in the compiler refereing to MLIR values? also can you defined more DTypes in Mojo using the __mlir* syntax? lets say Dtype.bfloat16, or Dtype.float5 (or any custom width numeric).
They're both defined in the standard library. There's currently no mechanism to add new DTypes (there is already one for
bfloat16
, but I don't know how complete the support is). You can find the list of current DTypes here: https://docs.modular.com/mojo/stdlib/builtin/dtype.html#dtype
Theoretically you can write a new type, as described in Low-Level IR with Mojo: https://docs.modular.com/mojo/notebooks/BoolMLIR.html ... but this is a really advanced topic that we don't have any documentation for at the moment.Modular Docs - Low-level IR in Mojo
Learn how to use low-level primitives to define your own boolean type in Mojo.
Modular Docs - dtype
Module
Thnx
@Arthur Evans that is super helpful! Would be great if the documentation explained the above (i'm contemplating a PR based on your explanation ;-)). I also can't wait for debugger support to be able to inspect memory layout.