在现代(流水线/超标量)处理器上执行x86 rep指令

时间:2011-12-08 01:23:20

标签: performance assembly x86 pipeline

我最近一直在写x86程序集(为了好玩),并且想知道rep前缀字符串指令是否实际上在现代处理器上具有性能优势,或者它们是否仅用于后向兼容性。

我能理解为什么当处理器一次只运行一条指令时,英特尔最初会实施转发指令,但现在使用它们有什么好处呢?

使用可以编译更多指令的循环,还有更多要填充管道和/或无序发布。现代处理器是为优化这些带有重复前缀的指令而构建的,还是在现代代码中很少使用的rep指令,它们对制造商来说并不重要?

3 个答案:

答案 0 :(得分:34)

在AMD和英特尔的优化指南中,这样的问题都有很多空间。在这个领域给出的建议的有效性具有“半衰期” - 不同的CPU代表行为不同,例如:

Intel Architecture Optimization Manual给出了表7-2中各种块复制技术(包括rep stosd)的性能比较数据。内存复制例程的相对性能,pg。 7-37f。,对于不同的CPU,再一次在其他CPU上最快的可能不是最快的。

在许多情况下,最近的x86 CPU(具有“字符串”SSE4.2操作)可以通过SIMD单元执行字符串操作,请参阅this investigation

要跟进所有这些(和/或当事情再次发生变化时不断更新),请阅读Agner Fog's Optimization guides/blogs

答案 1 :(得分:8)

除了FrankH的优秀答案;我想指出哪种方法最好也取决于字符串的长度,它的对齐方式,以及长度是固定的还是可变的。

对于小字符串(可能高达约16个字节),使用简单指令手动执行它可能更快,因为它避免了更复杂技术的设置成本(并且对于固定大小的字符串可以很容易地展开)。对于中等大小的字符串(可能从16字节到4 KiB),类似“REP MOVSD”(如果可能出现未对准,则会引入一些“MOVSB”指令)可能是最好的。

对于任何大于此的东西,有些人会想要进入SSE / AVX和预取等。更好的想法是修复调用者,以便不需要复制(或strlen()或其他)首先。如果你足够努力,你几乎总会找到一种方法。 注意:也要非常警惕“假定的”快速mempcy()例程 - 通常它们已经在大量字符串上进行了测试,而不是在更可能的微小/小/中等字符串上进行测试。

还要注意(出于优化而不是方便的目的)由于所有这些差异(可能是长度,对齐,固定或可变大小,CPU类型等),有一个多用途“memcpy()”的想法因为所有非常不同的案件都是近视的。

答案 2 :(得分:0)

由于没有人给你任何数字,我会给你一些我通过对我的垃圾收集器进行基准测试而得到的,这是非常重要的。我要复制的对象长度为60%16字节,其余30%为500 - 8000字节左右。

  • 前提条件:dstsrcn都是8的倍数。
  • 处理器:AMD Phenom(tm)II X6 1090T处理器64位/ linux

以下是我的三个memcpy变体:

手动编码while循环:

if (n == 16) {
    *dst++ = *src++;
    *dst++ = *src++;
} else {
    size_t n_ptrs = n / sizeof(ptr);
    ptr *end = dst + n_ptrs;
    while (dst < end) {
        *dst++ = *src++;
    }
}

ptruintptr_t的别名)。时间:101.16%

rep movsb

if (n == 16) {
    *dst++ = *src++;
    *dst++ = *src++;
} else {
    asm volatile("cld\n\t"
                 "rep ; movsb"
                 : "=D" (dst), "=S" (src)
                 : "c" (n), "D" (dst), "S" (src)
                 : "memory");
}

时间:103.22%

rep movsq

if (n == 16) {
    *dst++ = *src++;
    *dst++ = *src++;
} else {
    size_t n_ptrs = n / sizeof(ptr);
    asm volatile("cld\n\t"
                 "rep ; movsq"
                 : "=D" (dst), "=S" (src)
                 : "c" (n_ptrs), "D" (dst), "S" (src)
                 : "memory");
}

时间:100.00%

req movsq获得微弱优势。