3作者: ashvardanian19 天前原帖
今年早些时候,我花了一个月的时间重新审视我的编码习惯,并重新思考一些过去的设计选择。我希望在今年重写并改进我的开源软件库,但首先我需要对几个问题找到答案。也许这些问题会引起社区中其他人的共鸣。 - 协程在高性能工作中可行吗? - 我应该使用SIMD内建函数以提高代码清晰度,还是降级到汇编以便于库的分发? - 硬件在AVX-512和SVE中的向量化散布/聚集方面是否已经赶上? - 在Intel、Arm和AMD上,安全区和指针标记有何不同? - CPU和GPU张量核心(TCs)之间的吞吐量差距有多大? - 不对齐的内存访问和拆分加载的成本有多高,非时间加载/存储提供了什么收益? - 标准库的哪些部分对性能影响最大? - 错误处理策略在开销方面如何比较? - 懒惰求值范围的编译时间与运行时间之间的权衡是什么? - 元编程有哪些实际且非平凡的用例? - 使用io_uring与POSIX套接字进行Linux内核绕过有多困难? - 我们距离有效使用网络技术规范或异构执行器在C++中的应用还有多远? - 在嵌套容器中传播有状态分配器的最佳实践是什么,哪些库支持它们? 这些问题涵盖了从微内核优化(纳秒级)到分布式系统(微/毫秒延迟)的广泛主题。我没有在一篇文章中解决所有问题,而是将我的探索整理成一个代码库——扩展了我之前的Google Benchmark教程(<a href="https://ashvardanian.com/posts/google-benchmark" rel="nofollow">https://ashvardanian.com/posts/google-benchmark</a>)——作为性能实验的沙盒。 一些有趣的观察: - 编译器现在能够很好地向量化3x3x3和4x4x4的单/双精度乘法!尽管操作数量减少了70%,但较小的乘法速度仍然慢约60%,超越了我普通的SSE/AVX,并且与AVX-512的性能相差不到10%。 - Nvidia的张量核心在不同代际之间在数值类型、吞吐量、瓦片形状、线程同步(线程/四元组/波/波组)和操作数存储方面差异显著。后Volta时代,通常需要手动PTX(因为内建函数滞后),尽管新推出的TileIR(在GTC上介绍)承诺为密集线性代数内核带来改进。 - AI浪潮推动CPU和GPU在矩阵乘法吞吐量和编程复杂性上趋于一致。我花了一天时间调试TMM寄存器初始化,SME同样奇怪。Sierra Forest每个插槽有288个核心,而AVX10.2则放弃了对256位的支持,转而支持512位……考虑到CPU的进步,我在想是否还需要独立的Intel GPU? - 在常见的浮点范围内,标量正弦近似可以比标准实现快多达40倍,即使没有使用SIMD。不过这有点不够严谨;我希望更多的项目能记录误差范围,并提供像Sleef那样的1和3.5 ULP变体。 - 像CTRE这样的元编程工具可以比典型的正则表达式引擎快5倍,并且在构建解析器时比手工编写的有限状态机更简单。 - 曾经在复杂性和性能上明显不同(DPDK/SPDK与io_uring),现在差距正在缩小。虽然5.5之前的io_uring可以在回环IO上将UDP吞吐量提升4倍,但新的零拷贝和并发优化仍然具有挑战性。 这个代码库中包含了我最喜欢的CppCon讲座、GitHub代码片段和技术博客文章的链接。意识到许多高级概念在不同语言中处理方式不同,我还开始将示例移植到Rust和Python的独立代码库中。协程在各处看起来都不太好 :( 总体而言,这个研究项目是有收获的!大多数问题在代码中找到了答案——除了指针标记和安全区,这些在公共云中仍然让我感到困惑。我很想听听其他人的看法,特别是在比较FPGA上小矩阵乘法的高级综合与手写的VHDL/Verilog(针对整型)方面。如果你有其他有趣的、冷门的话题建议,请告诉我!