✨亮点

  • 查看Mojo 手册中的新GPU 基础部分以及使用 Mojo 和 MAX 驱动程序教程开始进行 GPU 编程,获取在 Mojo 中开始进行 GPU 编程的指南!

  • 该包中的某些 APIgpu已得到增强,以简化 GPU 的使用。


    • 如果您只执行一次 GPU 内核,那么您现在可以跳过将其入队之前的编译步骤,并将其直接传递给 DeviceContext.enqueue_function()

    • 用于在主机和 GPU 内存之间异步复制缓冲区的三个独立方法DeviceContext已合并为单个重载 enqueue_copy() 方法,用于同步复制的三个独立方法已合并为一个重载 copy_sync() 方法。

    • gpu.shuffle模块已重命名, gpu.warp以更好地反映其用途。

    • gpuAPI 文档已经扩展,并且layout包的 API 文档正在制作中,从核心类型、功能和特征开始。



      请参阅变更日志的标准库变更部分以了解更多信息。

  • 旧版borrowed/inout关键字和-> T as foo语法不再受支持,现在会产生编译器错误。请改用read/ mut/out 参数语法。有关更多信息,请参阅 Mojo 手册中的参数约定。

  • 标准库中有许多与字符串相关的更改。值得注意的是,Char 类型已重命名为 Codepoint,以更好地体现其存储单个 Unicode 代码点的预期用途。此外,相关方法和类型名称也已更新。有关更多详细信息,请参阅 标准库更改

  • 已添加对 128 位和 256 位有符号和无符号整数的支持。这包括DType别名 DType.int128、、DType.uint128DType.int256DType.uint256以及SIMD对 128 位和 256 位有符号和无符号元素类型的支持。请注意,这会暴露 LLVM 的功能(和限制),它可能并不总是为这些类型提供高性能,并且可能缺少除法、余数等运算。有关更多详细信息,请参阅 标准库更改


语言变化

  • 现在允许引用具有未绑定(或部分)绑定参数集的结构类型中的别名,只要引用的别名不依赖于任何未绑定的参数:


        struct StructWithParam[a: Int, b: Int]:
      alias a1 = 42
      alias a2 = a+1
    
    fn test():
      _ = StructWithParams.a1 # ok
      _ = StructWithParams[1].a2 # ok
      _ = StructWithParams.a2 # error, 'a' is unbound.

        struct StructWithParam[a: Int, b: Int]:  alias a1 = 42  alias a2 = a+1fn test():  _ = StructWithParams.a1 # ok  _ = StructWithParams[1].a2 # ok  _ = StructWithParams.a2 # error, 'a' is unbound.
  • Mojo 编译器现在会警告@parameter for循环展开因子过大(默认情况下 >1024),这会导致编译时间过长和生成的代码量过大。设置--loop-unrolling-warn-threshold为将默认值更改为其他阈值或0禁用警告。

  • Mojo 编译时解释器现在可以处理更多 LLVM 内部函数,包括返回浮点值的函数。这允许 round()在编译时上下文中使用函数时进行常量折叠。

  • Mojo 编译器现在只有一个编译时解释器。以前有两个:一个用于处理解析器中对依赖类型很重要的几个情况(但也有很多限制),另一个主要解释器在“实例化”时运行,完全通用。这很令人困惑,并导致了大量错误。我们现在已经删除了特殊情况的解析时解释器,用更通用的依赖类型解决方案取而代之。这一变化对大多数用户来说应该是不可见的,但应该可以解决许多长期存在的错误,并显著简化编译器实现,使我们能够更快地行动。


标准库变更

  • OptionalSpanInlineArray已添加到 prelude 中。现在您不再需要显式导入这些类型即可在程序中使用它们。

  • GPU 编程变化:


    • 现在,您可以跳过在将其入队之前先编译 GPU 内核的步骤,并将其直接传递给 DeviceContext.enqueue_function()


              from gpu.host import DeviceContextfn func():    print("Hello from GPU")with DeviceContext() as ctx:    ctx.enqueue_function[func](grid_dim=1, block_dim=1)

              from gpu.host import DeviceContextfn func():    print("Hello from GPU")with DeviceContext() as ctx:    ctx.enqueue_function[func](grid_dim=1, block_dim=1)

      但是,如果您多次重复使用相同的函数和参数,则每次入队将产生大约 50-500 纳秒的开销。因此,您仍然可以先编译该函数, DeviceContext.compile_function() 然后将其传递给它,DeviceContext.enqueue_function()如下所示:


              with DeviceContext() as ctx:  var compiled_func = ctx.compile_function[func]()  # Multiple kernel launches with the same function/parameters  ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)  ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)

              with DeviceContext() as ctx:  var compiled_func = ctx.compile_function[func]()  # Multiple kernel launches with the same function/parameters  ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)  ctx.enqueue_function(compiled_func, grid_dim=1, block_dim=1)
    • 以下方法 DeviceContext


      • enqueue_copy_to_device()

      • enqueue_copy_from_device()

      • enqueue_copy_device_to_device()


        已合并为一个重载 enqueue_copy() 方法。此外,方法:

      • copy_to_device_sync()

      • copy_from_device_sync()

      • copy_device_to_device_sync()


        已被合并为一个重载 copy_sync() 方法。

    • gpu.shuffle模块已重命名, gpu.warp以更好地反映其用途。例如:


              import gpu.warp as warpvar val0 = warp.shuffle_down(x, offset)var val1 = warp.broadcast(x)

              import gpu.warp as warpvar val0 = warp.shuffle_down(x, offset)var val1 = warp.broadcast(x)
  • 增加了对 128 位和 256 位有符号和无符号整数的支持。


    • 该结构体中添加了以下别名 DTypeDType.int128DType.uint128DType.int256DType.uint256

    • SIMD类型现在支持 128 位和 256 位有符号和无符号元素类型。请注意,这暴露了 LLVM 的功能(和局限性),它可能无法始终为这些类型提供高性能,并且可能缺少除法、余数等运算。

    • 已添加以下Scalar1 元素值的别名: 、、和 。SIMD``Int128``UInt128``Int256``UInt256

  • String和朋友们:


  • 收藏:


  • IntLiteral 和类型的设计FloatLiteral已更改,以将其编译时值保留为参数而不是存储字段。这正确地模拟了无限精度文字在运行时无法表示的情况,并消除了在极端情况下遇到的许多错误。这是通过编译器中增强的依赖类型支持实现的。

  • Buffer结构已被删除,取而代之的是 SpanNDBuffer

  • round()函数现已修复,执行“四舍五入为偶数”(也称为“银行家舍入”)而不是“四舍五入为远离零的一半”。

  • UnsafePointer.alloc() 方法已更改为生成带有空Origin参数的指针,而不是带有MutableAnyOrigin。这缓解了任何来源参数延长此通用方法的无关局部变量的生存期的问题。

  • 现在有更多的软件包已被记录下来。


    • compile包裹

    • gpu包裹

    • layout软件包正在进行中,从核心类型、功能和特征开始

  • 添加了新 sys.is_compile_time()功能。这使您能够查询代码是否在编译时执行。例如:


        from sys import is_compile_timefn check_compile_time() -> String:  if is_compile_time():      return "compile time"  else:      return "runtime"def main():    alias var0 = check_compile_time()    var var1 = check_compile_time()    print("var0 is evaluated at ", var0, " , while var1 is evaluated at ", var1)

        from sys import is_compile_timefn check_compile_time() -> String:  if is_compile_time():      return "compile time"  else:      return "runtime"def main():    alias var0 = check_compile_time()    var var1 = check_compile_time()    print("var0 is evaluated at ", var0, " , while var1 is evaluated at ", var1)

    将打印var0 is evaluated at compile time, while var1 is evaluated at runtime


工具变更

  • Mojo API 文档生成现在能够使用名称而不是索引来显示嵌套参数类型中的函数和结构参数引用。例如,


        sort[type: CollectionElement, //, cmp_fn: fn($1|0, $1|0) capturing -> Bool](span: Span[type, origin])

        sort[type: CollectionElement, //, cmp_fn: fn($1|0, $1|0) capturing -> Bool](span: Span[type, origin])

    现在显示


        sort[type: CollectionElement, //, cmp_fn: fn(type, type) capturing -> Bool](span: Span[type, origin])

        sort[type: CollectionElement, //, cmp_fn: fn(type, type) capturing -> Bool](span: Span[type, origin])

❌已移除

  • 使用传统的参数约定(例如inout,在命名结果中使用)as现在会产生错误消息而不是警告。

  • List.size已删除对 的直接访问。请改用公共 API。


    例子:


    扩展列表:


        base_data = List[Byte](1, 2, 3)data_list = List[Byte](4, 5, 6)ext_data_list = base_data.copy()ext_data_list.extend(data_list) # [1, 2, 3, 4, 5, 6]data_span = Span(List[Byte](4, 5, 6))ext_data_span = base_data.copy()ext_data_span.extend(data_span) # [1, 2, 3, 4, 5, 6]data_vec = SIMD[DType.uint8, 4](4, 5, 6, 7)ext_data_vec_full = base_data.copy()ext_data_vec_full.extend(data_vec) # [1, 2, 3, 4, 5, 6, 7]ext_data_vec_partial = base_data.copy()ext_data_vec_partial.extend(data_vec, count=3) # [1, 2, 3, 4, 5, 6]

        base_data = List[Byte](1, 2, 3)data_list = List[Byte](4, 5, 6)ext_data_list = base_data.copy()ext_data_list.extend(data_list) # [1, 2, 3, 4, 5, 6]data_span = Span(List[Byte](4, 5, 6))ext_data_span = base_data.copy()ext_data_span.extend(data_span) # [1, 2, 3, 4, 5, 6]data_vec = SIMD[DType.uint8, 4](4, 5, 6, 7)ext_data_vec_full = base_data.copy()ext_data_vec_full.extend(data_vec) # [1, 2, 3, 4, 5, 6, 7]ext_data_vec_partial = base_data.copy()ext_data_vec_partial.extend(data_vec, count=3) # [1, 2, 3, 4, 5, 6]

    有效地切片和扩展列表:


        base_data = List[Byte](1, 2, 3, 4, 5, 6)n4_n5 = Span(base_data)[3:5]extra_data = Span(List[Byte](8, 10))end_result = List[Byte](capacity=len(n4_n5) + len(extra_data))end_result.extend(n4_n5)end_result.extend(extra_data) # [4, 5, 8, 10]

        base_data = List[Byte](1, 2, 3, 4, 5, 6)n4_n5 = Span(base_data)[3:5]extra_data = Span(List[Byte](8, 10))end_result = List[Byte](capacity=len(n4_n5) + len(extra_data))end_result.extend(n4_n5)end_result.extend(extra_data) # [4, 5, 8, 10]
  • InlinedFixedVectorInlineList已被删除。相反, InlineArray在编译时已知上限时使用。如果直到运行时才知道上限,则Listcapacity 构造函数一起使用以最小化分配。


🛠️已修复