簡體   English   中英

在現代x86系統上,堆棧浮點數運算是否比堆浮點運算更快?

[英]Are stack float array ops faster than heap float ops on modern x86 systems?

在C float(或double)數組上,它足夠小以適應L1或L2高速緩存(大約16k),以及我在編譯時知道的大小,在它們使用的函數中定義它們通常有速度優勢,所以它們堆棧變量? 如果是這樣,差異很大? 我知道在過去,堆變量比堆棧變量要慢得多,但是現在cpu尋址和緩存的結構要復雜得多,我不知道這是不是真的。

我需要在'chunks'中對這些數組重復運行浮點數學,在同一個數組上反復重復(大約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位對齊(分別對於float和double),因此數組元素不會跨越緩存行邊界。 緩存行在x86上是64字節。

另一個重要的元素是確保編譯器使用SSE指令進行標量浮點運算。 這應該是現代編譯器的默認設置。 傳統浮點(也稱為387,具有80位寄存器堆棧)速度更慢,更難以優化。

如果經常分配和釋放此內存,請嘗試通過在池中,全局或在堆棧上分配來減少對malloc / free的調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM