在现代x86系统上,堆栈浮点数运算是否比堆浮点运算更快?

时间:2014-09-09 11:09:38

标签: c arrays performance floating-point

在C float(或double)数组上,小到足以适应L1或L2高速缓存(大约16k),以及我在编译时知道的大小,通常在它们用于它们的函数中定义它们的速度优势,所以它们是堆栈变量?如果是这样,差异很大?我知道在过去,堆变量比堆栈变量要慢得多,但是现在cpu寻址和缓存的结构要复杂得多,我不知道这是不是真的。

我需要在'chunks'中对这些数组重复运行浮点数学,在同一个数组上反复重复(大约1000次),我想知道是否应该在本地定义它们。我想将它们保存在最近/最快的位置将允许我以更快的速度重复迭代它们但我不理解缓存在这种情况下的含义。也许编译器或cpu足够聪明,可以实现我正在做的事情,并且在内部处理循环期间使这些数据阵列在硬件上高度本地化,而无需我的干预,也许它在这方面做得更好。

如果以这种方式加载大型数组,可能会冒着堆栈空间不足的风险?或者现代系统的堆栈空间不是很大?数组大小可以在编译时定义,我只需要一个数组和一个CPU,因为我需要坚持一个线程来完成这项工作。

3 个答案:

答案 0 :(得分:2)

分配和释放速度可能会有所不同。

在堆栈上分配只是从堆栈指针中减去所需的大小,这通常是在函数输入时对所有局部变量进行的,因此它基本上是免费的(除非使用alloca)。同样适用于在堆栈上释放内存。

在堆上分配需要调用mallocnew,这最终会执行一个数量级的指令。同样适用于freedelete

分配后,对阵列的访问速度应该没有区别。但是,堆栈更可能已经在CPU缓存中,因为先前的函数调用已经为局部变量使用了相同的堆栈内存区域。

如果您的架构使用Non-uniform memory access (NUMA),则当您的线程重新调度为在与最初分配内存的CPU不同的CPU上运行时,对不同内存区域的访问速度可能会有所不同。

对于受试者的深入治疗,请阅读What Every Programmer Should Know About Memory

答案 1 :(得分:2)

答案是:可能不是。

  1. 在i7等现代处理器上,L1 / L2 / L3缓存大小为64K / 1MB / 8MB,共享4x2内核。你的号码有点不对。
  2. 最值得担心的是并行性。如果你能让所有8个内核运行100%,这是一个良好的开端。
  3. 堆和堆栈内存之间没有区别,它只是内存。堆分配比堆栈分配慢,但希望你不要做太多。
  4. 缓存一致性很重要。缓存预取很重要。在内存中访问事物的顺序很重要。好好阅读:https://software.intel.com/en-us/blogs/2009/08/24/what-you-need-to-know-about-prefetching
  5. 但是在你能够进行基准测试之前,所有这些都是无用的。你无法改善无法衡量的东西。

  6. 评论:堆栈内存没有什么特别之处。通常重要的是将所有数据保持在一起。如果您经常访问本地变量,那么在堆栈旁边分配数组可能会有效。如果您有多个堆内存块,那么细分单个分配可能比单独分配更好。您只会知道您是否阅读了生成的代码和基准。

答案 2 :(得分:0)

它们的平均速度相同。假设数组占用的缓存行未被其他代码触及。

要确保的一件事是数组内存对齐至少为32位或64位对齐(分别为float和double),因此数组元素不会跨越缓存行边界。缓存行在x86上是64字节。

另一个重要元素是确保编译器使用SSE指令进行标量浮点运算。这应该是现代编译器的默认设置。传统的浮点(a.k.a 387,80位寄存器堆栈)速度慢得多,而且难以优化。

如果经常分配和释放此内存,请尝试通过在池中,全局或在堆栈上分配来减少对malloc / free的调用。