1

我正在编写一些旨在以 32 位模式在 x86 上运行的代码。在那种模式下,我知道我只有 8 个 SIMD/AVX2-Registers (YMM0-7) 可以自由使用。然而,我的一些向量子例程有时会同时使用超过这个数量的寄存器(这意味着它们仍然需要在路上的某个地方——大多数情况下不会那么远)。

我的理解是,编译器在找不到未使用的寄存器时会将旧寄存器导出到堆栈内存。但这对性能有多大影响?(例如,以后每次导出/导入的周期)。我是否可以信任主要位于 L1-D-Cache 中的堆栈内存(在 Haswell 中有 2 个周期延迟),或者避免这种寄存器到内存(反之亦然)传输是否会对性能产生重大影响?

到目前为止,我无法找到该主题的答案,特别是因为寄存器越来越大(即将推出的 Skylake 平台,每个寄存器 1 个缓存线)。如果您能提供消息来源以防您回答,那就太好了。

4

1 回答 1

1

命中内存总是有影响的。

写入通常很慢。但是,如果您只点击 L1 缓存,它几乎是瞬时的(几乎与将一个寄存器复制到另一个寄存器相同)。如果您点击 L2 或 L3,这会更慢,但仍然非常快。如果您使用实际内存,那将是“死”慢(相比之下)。因此,如果您的 L1 缓存为 12Kb,则您的堆栈上最多可以有 12Kb 的数据并且仍然可以非常快地工作(尽管请记住缓存在您的数据之间共享)以及您正在运行的代码;它可能是 6Kb 的指令缓存和 6Kb 的数据,包括堆栈。)

您将遇到的主要问题是您正在处理多少内存。如果您的输入数据非常大,那将产生最大的影响。特别是如果您不能以流式传输方式加载输入数据,而处理器已针对这些方式进行了很好的优化。(从 (eax) 读取 X 个字节,执行 eax + X,然后重复)。

请注意,如果您必须用汇编程序编写它,您将必须完成编译器可以为您完成的所有工作,并且零错误并完全优化。今天的编译器非常擅长优化(gcc/g++)。当您在堆栈上 PUSH 时,它变得特别复杂,更改当前堆栈上所有局部变量的偏移量(除非您使用帧指针。)

作为另一个细节,编译器将堆栈视为从函数中必需的所有局部变量的集合中定义的结构。所以访问堆栈与访问结构非常相似。

于 2014-09-07T00:46:28.313 回答