Go 中平台无关的 SIMD

Go 新推出的平台无关 SIMD API 旨在让底层向量化操作更易用,并能跨 CPU 保持可移植性,从而减少在性能关键代码中手写汇编或 C/C++ 的需求。评论者认为真实项目中已有明显加速,并欢迎这种兼顾可移植性与架构特定能力的分层设计,同时指出编译器自动向量化也在并行改进。讨论还再次触及 Go 在内存安全与数据竞争方面的权衡,以及其不断演进的性能特性如何使它在数据库、分析和机器学习等高性能工作负载中与 Rust、C++、Java 和 Mojo 等语言并列。

总体反响与早期体验

  • 许多评论者都很兴奋:这解决了长期以来高性能 Go 代码需要退回到 C/C++/汇编的需求。
  • 一些人已经报告了真实的速度提升(例如,图像前景估计约提升 30%;语音模型推理有可测的收益;浏览器调色板交换演示中,相比标量代码快约 5 倍,而可移植 SIMD 仅比架构特定 SIMD 慢约 11%)。
  • 这被认为对数据库、分析以及其他多核、数值型或适合向量化的工作负载尤其有益。

SIMD 与自动向量化

  • 有人指出,对于许多工作负载,编译器的自动向量化已经“足够好”,并感叹这个特性并没有直接解决这一差距。
  • 也有人提到,Go 编译器的自动向量化工作正在积极推进,而显式 SIMD 与更好的自动向量化是互补的。
  • 还有建议认为可以加入 lint 工具或其他工具,自动把合适的循环转换成 SIMD 模式。

互操作、汇编与性能

  • 关于 CGO 开销的抱怨依然存在:Go 的内存模型和并发模型与 C 不同,因此跨边界调用的代价仍然很高。
  • 少数人建议在性能关键路径上使用 Go 汇编而不是 CGO;一些项目已经在 Go 汇编中大量使用 SIMD。

API 设计与可移植性

  • 分层设计(架构特定的 archsimd 加上可移植的 simd)受到称赞;人们喜欢通过启动时的多版本机制把派发开销提升到调用者层面。
  • 一个担忧是:由于使用 SIMD 的函数会生成多个专门化副本,代码体积可能增长;这种对真实二进制文件大小的影响尚不明确。
  • 这种方式因对可变长度向量 ISA(如 SVE 和 RISC-V RVV)更友好而受到赞扬,因为它避免了在类型系统中固定向量大小。

内存安全与数据竞争

  • 一大段分支讨论了在多字值(切片、字符串、接口)上发生数据竞争时,Go 是否仍算“内存安全”,因为这会导致撕裂、越界访问、panic,原则上甚至可能造成内存破坏。
  • 有人认为“内存安全”是安全领域里的术语;按这种常见定义,除非使用 unsafe 或发生数据竞争,否则 Go 是内存安全的。
  • 也有人坚持认为,由竞争引发内存破坏的可能性意味着 Go 并非完全内存安全,尤其是与那些内存模型可以排除这类行为的语言相比。

语言比较与理念

  • 评论者把 Go 与 Rust、Java、C#、D、Zig、Julia、Swift、C++(包括 std::simd)、Mojo 以及 WebAssembly SIMD 做了比较。
  • 他们强调了 Go 保守的设计理念——“少做事,但把事做好”——并指出这与泛型长期推进的过程有相似之处。
  • 有些人觉得 Rust 更有势头,但也认为两种语言都有稳定的适用领域。

其他

  • 有一小段偏题讨论了“API”的定义。
  • 几个人抱怨 Go 官方文档缺少语法高亮;也有人为极简或不使用高亮的做法辩护。