2016-09-29 75 views
4

我的計算機有64位處理器,並且當我尋找sizeof(int)sizeof(long)sizeof(long long),事實證明,INT是32位,並且長長是64位。我研究了其中的原因,並且似乎在C++中符合機器字大小的流行假設是錯誤的。據我瞭解,由編譯器決定什麼是規模,而我的是Mingw-w64。我的研究理由是,如果使用小於字號的字體對字體速度有利(例如,int),或者它有負面影響。在32位系統中,一個流行的觀點是:由於字長爲int,short將被轉換爲int並且它會導致額外的位移等,從而導致更差的性能。反對的意見是,緩存級別會有好處(我沒有深入),並且使用short對於虛擬內存的經濟性將是有用的。所以,除了這種困境之間的混亂之外,我還面臨着另一個問題。我的系統是64位的,如果我使用intshort,它仍然會小於字的大小,並且我開始認爲使用64位長長,因爲它在系統設計的水平。另外我讀到還有另一個約束,即定義類型大小的OS(庫函數(ILP64,LP64))。在ILP64默認INT是64位與LP64相反,如果我使用支持ILP64的操作系統,它會加快程序嗎?一旦我開始問我應該用哪種類型來加速我的C++程序,我面臨着更多的深層次的話題,我沒有專業知識,而且一些解釋似乎與彼此矛盾。你能解釋一下嗎?C++ INT VS在64位機器長長

1)如果最好的做法是在x64中使用long long,即使對於1-4字節的數據也能獲得最大性能?

2)權衡在使用A型小於字大小(存儲器贏VS附加操作)

3)是否在x64計算機,其中字& INT大小爲64位,具有處理短的可能性,通過使用所謂的向後兼容性使用16位字大小?或者它必須將16位文件放到64位文件中,並且可以完成的事實將系統定​​義爲向後兼容。

4)我們可以強制編譯器使64位的int

5)如何將ILP64整合到使用LP64的PC?

6)使用適用於上述問題的代碼與其他編譯器,操作系統和體系結構(32位處理器)一起使用的代碼有哪些可能的問題?

+2

永遠不要依賴標準數據類型來獲得特定的大小。爲此,C++ 11具有[固定寬度整數類型](http://en.cppreference.com/w/cpp/types/整數)。 (在C++ 11之前有編譯器特定的類型) – UnholySheep

+0

你可以有一個512位的CPU和一個16位的'int'仍然是100%符合標準。爲什麼任何人都會這樣做,但這仍然是合法的。 – user4581301

回答

15

1)如果最好的做法是在x64中使用long long,即使對於1-4字節的數據也能實現最高性能?

不,它可能實際上會讓你的表現更糟。例如,如果您使用64位整數,而您可以使用32位整數,那麼您只需將處理器和內存之間必須發送的數據量增加一倍,並且內存的速度要慢幾個數量級。所有的高速緩存和內存總線都會浪費兩倍的速度。

2)權衡使用類型小於字大小(內存勝利VS額外的操作)

一般的性能於一體的現代化機器的主要驅動力將是多少數據需要存儲以便運行程序。一旦程序的工作集大小超過了寄存器,L1緩存,L2緩存,L3緩存和RAM的容量,您將看到顯着的性能懸崖。

此外,如果您的編譯器足夠聰明,可以指出如何使用處理器的向量指令(又名SSE指令),那麼使用較小的數據類型可能會成功。現代矢量處理單元足夠聰明,可以將8個16位短整數塞入與兩個64位長整數相同的空間,因此您可以一次執行四倍的操作。

3)是否有一個x64計算機的字& int大小爲64位,有可能通過使用所謂的向後兼容性處理短,使用16位字大小?或者它必須將16位文件放到64位文件中,並且可以完成的事實將系統定​​義爲向後兼容。

我不確定你在問什麼。通常,64位機器能夠執行32位和16位可執行文件,因爲這些較早的可執行文件使用64位機器潛力的子集。硬件指令集通常是向後兼容的,這意味着處理器設計者傾向於增加功能,但很少移除功能。

4)我們可以強制編譯器使int 64位?

所有編譯器都有相當標準的擴展名,允許您使用固定位數的數據。例如,頭文件stdint.h聲明類型,如int64_tuint64_t

5)如何將ILP64到使用LP64 PC?

https://software.intel.com/en-us/node/528682

6)什麼是使用適合於上述問題和其它編譯器,OS的代碼的可能的問題,和體系結構(32位處理器)?

一般來說,編譯器和系統足夠聰明,可以知道如何在任何給定的系統上執行代碼。但是,32位處理器將不得不做額外的工作來處理64位數據。換句話說,正確性不應該是一個問題,但性能會是。

但是,一般情況下,如果性能對您來說確實非常重要,那麼無論如何您都需要針對特定​​架構和平臺進行編程。

澄清要求:非常感謝!我想澄清問題1:1。你說這對記憶不好。讓我們以32位int爲例。當你將它發送到內存時,因爲它是64位系統,對於所需的整數0xeeee ee,當我們發送它時它不會變爲0xeeeeeeeee + 32其他位?當字長爲64位時,處理器如何發送32位? 32位是所需的值,但不會與32個未使用的位組合使用並以此方式發送?如果我的假設是真的,那麼記憶就沒有區別。

這裏有兩件事要討論。

首先,您所討論的情況不會發生。處理器不需要將32位值「升級」爲64位值以便適當地使用它。這是因爲現代處理器具有不同的訪問模式,能夠適當地處理不同大小的數據。

例如,64位英特爾處理器有一個名爲RAX的64位寄存器。但是,通過將該寄存器稱爲EAX,即使在16位和8位模式下,也可以在32位模式下使用該寄存器。我偷的圖從這裏:

x86_64 registers rax/eax/ax/al overwriting full register contents

1122334455667788 
================ rax (64 bits) 
     ======== eax (32 bits) 
      ==== ax (16 bits) 
      == ah (8 bits) 
       == al (8 bits) 

編譯器和彙編之間,產生正確的代碼,使得一個32位的值被適當地處理。

其次,當我們談論內存開銷和性能時,我們應該更具體。現代存儲器系統由磁盤,主存儲器(RAM)和典型的兩個或三個高速緩存(例如L3,L2和L1)組成。可以在磁盤上尋址的最小數量的數據稱爲頁面,,頁面大小通常爲4096字節(儘管它們不一定是)。然後,可以在內存中尋址的最小數量的數據被稱爲緩存行,,其通常遠大於32或64位。在我的電腦上,緩存行大小爲64字節。處理器是數據在字級和以下實際傳輸和尋址的唯一地方。

所以如果你想改變一個位於磁盤上的文件中的一個64位字,那麼在我的計算機上,這實際上要求你將4096字節從磁盤加載到內存中,然後從內存加載64字節L3,L2和L1高速緩存,然後處理器從L1高速緩存中獲取單個64位字。

結果是字大小對於內存帶寬沒有任何意義。但是,您可以將32位整數中的16個整合到同一空間中,您可以打包這些64位整數中的8個整數。或者你甚至可以在同一個空間中放32個16位值或64個8位值。如果您的程序使用許多不同的數據值,則可以使用必需的最小數據類型顯着提高性能。

+0

非常感謝!我想澄清問題1:1。你說這對記憶不好。讓我們以32位int爲例。當你將它發送到內存時,因爲它是64位系統,對於所需的整數0xeeee ee,當我們發送它時它不會變爲0xeeeeeeeee + 32其他位?當字長爲64位時,處理器如何發送32位? 32位是所需的值,但不會與32個未使用的位組合使用並以此方式發送?如果我的假設是真的,那麼記憶就沒有區別。 – UserRR

+0

@UserRR您有一個64位寄存器和一個64位總線,但高速緩存和RAM仍然只是一排位。如果指定32位,則使用32位。 – user4581301

+0

@UserRR更新答案與答覆 – David