gpt4 book ai didi

performance - rep stosb 指令如何比等效循环执行得更快?

转载 作者:行者123 更新时间:2023-12-03 05:17:17 32 4
gpt4 key购买 nike

怎么才能使用说明rep stosb执行速度比这段代码快?

    Clear: mov byte [edi],AL       ; Write the value in AL to memory
inc edi ; Bump EDI to next byte in the buffer
dec ecx ; Decrement ECX by one position
jnz Clear ; And loop again until ECX is 0

是否保证在所有现代 CPU 上都如此?我应该总是更喜欢使用 rep stosb而不是手动编写循环?

最佳答案

在现代 CPU 中,rep stosb的和 rep movsb的微编码实现实际上使用比 1B 更宽的存储,因此它可以比每个时钟一个字节快得多。

( 注意这仅适用于 stos 和 movs,而不适用于 repe cmpsbrepne scasb 。不幸的是,它们仍然很慢,就像在 Skylake 上相比每字节最多 2 个周期,这与 AVX2 相比是可悲的vpcmpeqb 用于实现 memcmp 或 memchr。参见 https://agner.org/optimize/ 获取指令表,以及 the x86 tag wiki 中的其他性能链接。

Why is this code 6.5x slower with optimizations enabled?举个 gcc 不明智内联的例子 repnz scasb或者对 strlen 来说不那么糟糕的标量比特黑客碰巧变大了,还有一个简单的 SIMD 替代方案。)

rep stos/movs具有显着的启动开销,但对于大型 memset/memcpy 上升良好. (有关何时使用 rep stos 与小缓冲区的矢量化循环的讨论,请参阅 Intel/AMD 的优化手册。)尽管如此,如果没有 ERMSB 功能,rep stosb已针对中小型 memset 进行了调整,最好使用 rep stosdrep stosq (如果您不打算使用 SIMD 循环)。

使用调试器单步执行时,rep stos只进行一次迭代(ecx/rcx 递减一次),因此微码实现永远不会进行。不要让这愚弄您认为它只能做这些。

What setup does REP do?有关英特尔 P6/SnB 系列微架构如何实现的一些详细信息 rep movs .

Enhanced REP MOVSB for memcpy使用 rep movsb 考虑内存带宽与 SSE 或 AVX 循环相比,在具有 ERMSB 功能的 Intel CPU 上。 (特别要注意的是,多核至强 CPU 不能仅用一个线程来使 DRAM 带宽饱和,因为一次传输中的缓存未命中数以及 RFO 与非 RFO 存储协议(protocol)的限制。)

现代英特尔 CPU 应该在每个时钟一次迭代中运行问题中的 asm 循环,但 AMD 推土机系列内核可能甚至无法在每个时钟管理一个存储。 (处理 inc/dec/branch 指令的两个整数执行端口的瓶颈。如果循环条件是 edi 上的 cmp/jcc,AMD 内核可以对比较和分支进行宏融合。)

所谓的快速字符串操作(英特尔 P6 和 SnB 系列 CPU 上的 rep movsrep stos)的一个主要特点是,当存储到以前没有缓存的内存时,它们避免了为所有权读取缓存一致性流量。所以这就像使用 NT 存储写入整个缓存行,但仍然是强排序的。(ERMSB 功能确实使用弱排序存储)。

IDK AMD 的实现有多好。

(更正:我之前说过英特尔 SnB 只能处理每 2 个时钟一个的分支吞吐量,但实际上它可以在每个时钟一次迭代中运行小循环。)

请参阅从 链接的优化资源(特别是 Agner Fog 的指南)标记维基。

Intel IvyBridge 和后来的 ERMSB,这让 rep stos[b/w/d/q]rep movs[b/w/d/q]使用弱排序的存储(如 movnt ),允许存储提交无序缓存。如果 L1 缓存中并非所有目标都已热,则这是一个优势。我相信,从文档的措辞来看,there's an implicit memory barrier at the end of a fast string op ,因此任何重新排序仅在由字符串 op 创建的存储之间可见,而不是在它与其他存储之间可见。即你仍然不需要 sfence之后 rep movs .

因此,对于 Intel IvB 及更高版本上的大型对齐缓冲区,rep stos memset 的实现可以击败任何其他实现。一个使用 movnt存储(不会将数据留在缓存中)也应该接近饱和主内存写入带宽,但实际上可能跟不上。请参阅有关对此的讨论的评论,但我找不到任何数字。

对于小缓冲区,不同的方法有非常不同的开销。微基准测试可以使 SSE/AVX 复制循环看起来比它们更好,因为每次都以相同的大小和对齐方式进行复制可以避免启动/清理代码中的分支错误预测。 IIRC,建议对 Intel CPU 上 128B 以下的副本使用矢量化循环(不是 rep movs )。阈值可能高于此值,具体取决于 CPU 和周围代码。

Intel 的优化手册也讨论了不同 memcpy 实现的开销,以及 rep movsb对错位的惩罚比 movdqu 更大.

请参阅优化的 memset/memcpy 实现的代码,以获取有关实践中所做操作的更多信息。 (例如 Agner Fog 的图书馆)。

关于performance - rep stosb 指令如何比等效循环执行得更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33480999/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com