将寄存器导出到堆栈对性能有何影响?



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

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

到目前为止,我还没能找到这个话题的答案,尤其是因为寄存器越来越大(即将推出的Skylake平台每个寄存器有1个缓存线)。如果你能提供消息来源以备不时之需,那就太好了。

命中内存总是有影响的。

写入通常很慢。然而,如果你只访问一级缓存,它几乎是即时的(几乎与将寄存器复制到另一个寄存器相同)。如果你访问二级或三级缓存,速度会较慢,但仍然非常快。如果你达到了实际内存,那就"死"慢了(相比之下)。因此,如果你的一级缓存是12Kb,你的堆栈上可以有多达12Kb的数据,并且仍然工作得很快(尽管记住,缓存是在你的数据和你正在运行的代码之间共享的;它可能是6Kb的指令缓存和6Kb包括堆栈在内的数据。)

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

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

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

最新更新