c-在现代x86系统上,堆栈浮点数组操作比堆浮点操作快



在C float(或double)数组上,小到可以放入一级或二级缓存(约16k),而且我在编译时知道它的大小,在它们所使用的函数中定义它们通常有速度优势吗,所以它们是堆栈变量?如果是的话,这是一个很大的区别吗?我知道在过去,堆变量比堆栈变量慢得多,但现在cpu寻址和缓存的结构要复杂得多,我不知道这是不是真的。

我需要在这些数组上以"块"的形式重复进行浮点运算,在相同的数组上一遍又一遍(大约1000次),我想知道是否应该在本地定义它们。我想把它们放在最近/最快的位置可以让我更快地重复迭代,但我不理解缓存在这种情况下的含义。也许编译器或cpu足够聪明,可以在没有我干预的情况下实现我正在做的事情,并在内部处理循环中使这些数据阵列在硬件上高度本地化,也许它在这方面做得比我更好。

如果我以这种方式加载大型数组,可能会有耗尽堆栈空间的风险?或者堆栈空间在现代系统中没有受到很大限制?数组大小可以在编译时定义,我只需要一个数组和一个CPU,因为我需要坚持使用一个线程来完成这项工作。

分配和解除分配的速度可能会有所不同。

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

在堆上进行分配需要调用mallocnew,这最终会执行更多数量级的指令。freedelete也是如此。

一旦分配了阵列,访问阵列的速度应该不会有差异。然而,堆栈更有可能已经在CPU缓存中,因为以前的函数调用已经为局部变量使用了相同的堆栈内存区域。

如果您的体系结构使用非统一内存访问(NUMA),那么当您的线程被重新调度在与最初分配内存的CPU不同的CPU上运行时,对不同内存区域的访问速度可能会有所不同。

为了深入了解这个主题,请阅读《每个程序员都应该知道的关于内存的知识》。

答案是:可能不会。

  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. 但是,在你能够进行基准测试之前,所有这些都是无用的。你无法改进你无法衡量的东西

重新评论:堆栈内存没有什么特别之处。通常重要的是将所有数据紧密地放在一起。如果您经常访问局部变量,那么在堆栈上分配它们旁边的数组可能会起作用。如果您有几个堆内存块,那么细分单个分配可能比单独分配效果更好。只有阅读了生成的代码和基准测试,您才会知道。

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

需要确保的一点是,阵列内存对齐至少是32位或64位对齐的(分别用于浮点和双精度),这样阵列元素就不会跨越缓存线边界。x86上的缓存线为64字节。

另一个重要元素是确保编译器使用SSE指令进行标量浮点运算。这应该是现代编译器的默认设置。传统的浮点(又称387,具有80位寄存器堆栈)要慢得多,也更难优化。

如果频繁地分配和释放这个内存,请尝试通过在池中、全局或堆栈上分配它来减少对malloc/free的调用。

最新更新