【问题标题】:Performance comparison of atomic operations on different sizes不同大小的原子操作性能对比
【发布时间】:2015-03-28 20:26:28
【问题描述】:

在处理器的自然字大小(4 字节或 8 字节)上运行的原子操作的性能与在其他大小(2 字节或 1 字节)上运行的性能相比如何?

如果我需要维护一个布尔原子变量,我试图找出最佳做法是:使用 1 字节优化空间,或使用 4/8 字节(可能)优化性能。

【问题讨论】:

    标签: performance c++11 atomic


    【解决方案1】:

    http://agner.org/optimize/ 了解更多详情。

    在 x86 上,1 字节数据的数组应该是好的。它可以像使用普通的mov 一样快地加载movzx(零扩展)。

    x86 具有支持原子位域的位操作,如果您想将数据打包另一个 8 倍。不过,我不确定编译器在为这种情况下制作高效代码方面的表现如何。即使是只写操作也需要一个缓慢的原子 RMW 周期来保存您要写入的位的字节。 (在 x86 上,它将是一条 lock OR 指令,这是一个完整的内存屏障。在 Intel Haswell 上它是 8 微指令,而字节存储是 1。吞吐量是 19 倍。)如果它可能仍然值得表示大量缓存未命中和少量缓存未命中之间的差异,尤其是。如果大部分访问是只读的。 (读一点很快,和非原子情况完全一样。)

    2 字节(16 位)操作在 x86 上可能很慢,尤其是。在英特尔 CPU 上。当英特尔指令解码器必须使用 16 位立即操作数解码指令时,它们的速度会大大降低。这是操作数大小前缀中的dreaded LCP stall。 (8b 操作具有完全不同的操作码,32 位和 64 位由 REX 前缀选择,这不会减慢解码器的速度)。所以 16b 是奇一出,你应该小心使用它。最好将 16b 内存加载到 32b 变量中,以避免在使用临时变量时出现部分寄存器惩罚和 16 位立即数。 (AMD CPU 在处理movzx 负载时效率不高(需要一个 ALU 单元和额外的 1 个周期延迟),但内存的节省几乎总是值得的(出于缓存原因)。


    32b 是用于局部临时变量的“最佳”大小。选择该大小不需要前缀(增加代码密度),并且在使用低 8b 后再次使用完整寄存器时不会出现部分寄存器停顿或额外的微指令。我相信这是 int_fast32_t 类型的目的,但在 x86 Linux 上,不幸的是该类型是 64 位的。

    【讨论】:

    • 谢谢,您指的是关于 anger.org/optimize 的具体手册吗?
    • @firo:主要是说明表和微架构指南,以了解什么是微指令以及为什么这些很重要。另请参阅 stackoverflow.com/tags/x86/info 中的其他性能链接,尤其是 uops.info,以了解所有指令的自动化测试,以避免在 Agner 的结果中偶尔出现拼写错误。
    猜你喜欢
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多