我正在研究一些在32位模式下在x86上运行的代码。在那种模式下,据我所知,我只有8个SIMD / AVX2寄存器(YMM0-7)可以自由使用。但是,我的一些矢量子程序有时会同时使用超过这个数量的寄存器(这意味着它们在未来的某个地方仍然需要它们 - 大多数情况下不会在此之后)。
我的理解是,当编译器找不到未使用的寄存器时,它们会将旧寄存器导出到堆栈存储器。但这对性能有多大影响? (例如,稍后每次出口/进口的周期)。我是否可以信任主要驻留在L1-D-Cache中的堆栈内存(Haswell中有2个周期的延迟),或者是否存在避免这种寄存器到内存(反之亦然)传输的显着性能影响?
到目前为止,我无法找到这个主题的答案,特别是因为寄存器越来越大(每个寄存器的一个Cacheline与即将推出的Skylake平台)。如果你可以在你回答的情况下给出来源,那就太好了。
答案 0 :(得分:1)
记忆力总会受到影响。
写入通常很慢。但是,如果你只是点击L1缓存,它接近瞬时(几乎与将寄存器复制到另一个寄存器相同。)如果你点击L2或L3,那就慢,但仍然非常快。如果你达到实际内存,那就“死”慢(相比之下)。所以如果你的L1缓存是12Kb,你的堆栈上最多可以有12Kb的数据并且仍然可以非常快地工作(尽管记住你的数据之间共享缓存)和你正在运行的代码;它可能是6Kb的指令缓存和6Kb的数据,包括堆栈。)
你要遇到的主要问题是你正在处理多少内存。如果您的输入数据非常大,那将产生最大的影响。特别是如果您无法以流式方式加载输入数据,而处理器已经过优化。 (从(eax)读取X字节,执行eax + X,然后重复)。
请注意,如果必须在汇编程序中编写它,则必须完成编译器可以为您执行的所有工作,并且没有错误并且已完全优化。今天的编译器非常擅长优化(gcc / g ++)。当你在堆栈上推送时,它会变得特别复杂,改变当前堆栈上所有局部变量的偏移量(除非你使用帧指针。)
作为另一个细节,编译器将堆栈视为从函数中所需的所有局部变量集合定义的结构。因此访问堆栈与访问结构非常相似。