相关疑难解决方法(0)

英特尔Skylake上的商店循环出乎意料的糟糕和奇怪的双峰性能

我看到一个简单的存储循环出乎意料地表现不佳,这个存储循环有两个存储:一个具有16字节的正向步长,另一个总是位于同一位置1,如下所示:

volatile uint32_t value;

void weirdo_cpp(size_t iters, uint32_t* output) {

    uint32_t x = value;
    uint32_t          *rdx = output;
    volatile uint32_t *rsi = output;
    do {
        *rdx    = x;
        *rsi = x;

        rdx += 4;  // 16 byte stride
    } while (--iters > 0);
}
Run Code Online (Sandbox Code Playgroud)

在汇编这个循环可能3看起来像:

weirdo_cpp:

...

align 16
.top:
    mov    [rdx], eax  ; stride 16
    mov    [rsi], eax  ; never changes

    add    rdx, 16

    dec    rdi
    jne    .top

    ret
Run Code Online (Sandbox Code Playgroud)

当访问的存储区域在L2中时,我希望每次迭代运行少于3个周期.第二个商店只是一直在同一个位置,应该添加一个周期.第一个商店意味着从L2引入一条线,因此每4次迭代也会驱逐一条线.我不确定你如何评估L2成本,但即使你保守估计L1只能在每个周期中执行以下操作之一:(a)提交商店或(b)从L2接收一行或(c)将一条线驱逐到L2,对于stride-16商店流,你会得到1 + 0.25 + …

optimization performance x86 assembly x86-64

25
推荐指数
2
解决办法
1629
查看次数

如果预取在加载之前没有完成,那么预取就没用了吗?

假设我们有这个伪代码,但它ptr不在任何 CPU 缓存中:

prefetch_to_L1 ptr
/* 20 cycles */
load ptr
Run Code Online (Sandbox Code Playgroud)

由于ptr在主存中,预取操作的延迟(从预取指令解码到ptr在L1高速缓存中可用)远大于20个周期。正在进行的预取是否会减少负载的延迟?或者预取除非在加载之前完成,否则就没用吗?

天真地(对内存系统如何工作没有太多了解)我可以看到它以两种方式工作:

  • 当 CPU 执行加载时,它会以某种方式识别出同一地址正在进行预取,并等待预取完成后再从 L1 加载。
  • CPU 发现该地址当前不在高速缓存中,并转到主内存,忽略并行执行的预取操作。

其中之一是正确的吗?还有我没有想到的第三种选择吗?我对 Skylake 特别感兴趣,但也只是想建立一些一般的直觉。

optimization performance intel cpu-architecture micro-architecture

5
推荐指数
0
解决办法
75
查看次数

_builtin_prefetch() 中第二个参数的作用是什么?

此处的 GCC 文档指定了 _buitin_prefetch 的用法。

第三个论点是完美的。若为0,编译器产生prefetchtnta(%rax)指令 若为1,编译器产生prefetcht2(%rax)指令 若为2,编译器产生prefetcht1(%rax)指令 若为3(默认),编译器产生prefetcht0 (%rax) 指令。

如果我们改变第三个参数,操作码已经相应地改变了。

但是第二个参数似乎没有任何效果。

__builtin_prefetch(&x,1,2);
__builtin_prefetch(&x,0,2);
__builtin_prefetch(&x,0,1);
__builtin_prefetch(&x,0,0);
Run Code Online (Sandbox Code Playgroud)

以上是生成的示例代码:

以下是组装:

 27:    0f 18 10                prefetcht1 (%rax)
  2a:   48 8d 45 fc             lea    -0x4(%rbp),%rax
  2e:   0f 18 10                prefetcht1 (%rax)
  31:   48 8d 45 fc             lea    -0x4(%rbp),%rax
  35:   0f 18 18                prefetcht2 (%rax)
  38:   48 8d 45 fc             lea    -0x4(%rbp),%rax
  3c:   0f 18 00                prefetchnta (%rax)
Run Code Online (Sandbox Code Playgroud)

可以观察到第三个参数的操作码的变化。但即使我更改了第二个参数(指定读或写),汇编代码也保持不变。<27,2a> 和 <2e,31>。所以它不会向机器提供任何信息。那么第二个论点的目的是什么?

c x86 assembly gcc prefetch

4
推荐指数
2
解决办法
1556
查看次数