2017-04-22 248 views
13

最近我看到了一個編譯器如何組合兩個32位整數,它們是一個類的屬性值,並將它們存儲爲一個64位整數。我現在的問題是,爲什麼這樣做?結合整數有什麼優勢?爲什麼要將兩個32位整數合併成一個64位整數?

例如,如果我們有一個類

class FooBar { 
int x = 1; 
int y = 100; 
} 

以下屬性,以便代替

i32 = 00000001 
i32 = 01100100 

我們得到:

i64 = 0000000101100100 

你爲什麼要結合呢?

+6

我的猜測是該寄存器使用64位。它只使用一個寄存器來存儲這兩個寄存器,而不是使用兩個寄存器。 –

+0

爲什麼不呢?如果機器以64位整數工作效率更高,那麼這可能是一場勝利。你爲什麼在乎? –

+2

CPU通常不具有類型。像「int」這樣的東西是你的程序的一個屬性,而不是機器代碼的屬性。將這種「組合」稱爲「合併」並不合適,因爲前後是完全不同域的組成部分。 –

回答

10

現有的(當我寫這篇文章的時候)答案和評論雖然部分正確,卻錯過了這個優化的要點。它是用一條指令(使用64位數據)替換兩條指令(使用32位數據)。這會導致代碼大小和執行時間的輕微縮短。

編譯器使用一個64位指令初始化兩個變量(因爲它們共享連續的內存地址)。這些變量是分開的,並且將分開訪問。不需要移位或掩蔽。

當許多成員初始化時,這在構造函數中經常出現。一個常見的情況是零初始化,編譯器會將寄存器清零,然後使用該值初始化多個成員,將寫入連續的存儲器地址與較大的單次寫入相結合(例如,通過寫入一個16位短零值而不是兩個8位)。

+0

接受你的答案,因爲我覺得它是更完整。 – Asperger

+0

這是一個完美的答案,認真。謝謝 – Asperger

+3

>不需要移位或掩蔽。 我不同意這一點。您必須將內存空間別名爲4字節對齊。請參閱此鏈接:https://software.intel.com/en-us/articles/coding-for-performance-data-alignment-and-structures 這麼說,我認爲你是正確的,別名地址爲32或在性能方面,64接近「免費」。很好的答案。 – Sam

5

我相信你正在觀察優化。英特爾指令(如PADDSW)假定有多個打包操作數。

https://en.wikipedia.org/wiki/X86_instruction_listings

也有益處只用在64位架構的緩存1項。

如果您只需要其中一個值,則需要解壓縮代碼,但我懷疑代碼優化器正在運行的任何代碼都會有更好的存儲性能。

將C結構的所有成員對齊到字邊界上是正常的。這是一個單獨的char和一個int不會被打包,但與機器的字大小對齊。因此,struct { char, int}將具有8個字節的sizeof(..)。我猜這種情況翻轉了?

非常有趣。

+0

您可能聽說過webassembly?他們正在那裏做。你所說的真的很有趣 – Asperger

+0

「PAD ...」指令適用於SIMD。他們打包的值都是相同的類型。由於個別值仍然具有正常地址,因此解包無需花費。 –

相關問題