適用于遊戲開發人員的 64 位程式設計
處理器製造商只會在其桌上型電腦中運送 64 位處理器,甚至大部分膝上型電腦晶片組都支援 x64 技術。 對於遊戲開發人員而言,請務必利用 64 位處理器為其新應用程式提供的改進,並確保其先前的應用程式在新的處理器和 64 位版本的 Windows Vista 和 Windows 7 上正確執行。 本文說明相容性和移植問題,並協助開發人員輕鬆轉換至 64 位平臺。
Microsoft 目前有下列 64 位作業系統:
- Windows 10
- Windows 11
- Windows Server 2019 或更新版本
過去 64 位作業系統:
- Windows Server 2003 Service Pack 1
- WINDOWS XP Professional x64 Edition (可供 OEM 和開發人員透過 MSDN)
- Windows Vista
- Windows 7
- Windows 8.0
- Windows 8.1
- Windows Server 2008 - 2016
注意
Windows Server 2008 R2 或更新版本僅適用于 64 位版本。 Windows 11僅適用于 64 位或 ARM64 版本。
- 可定址記憶體的差異
- 在建置時指定大型位址感知
- 64 位平臺上 32 位應用程式的相容性
- 將應用程式移植到 64 位平臺
- 已移植應用程式的分析和優化
- 64 位作業系統上的 Managed 程式碼
- 執行 64 位作業系統的效能影響
- 總結
可定址記憶體的差異
大部分開發人員注意到的第一件事是,64 位處理器提供可定址的實體和虛擬記憶體數量大幅提升。
32 位平臺上的 32 位應用程式最多可以處理 2 GB。
使用 /LARGEADDRESSAWARE:YES 連結器旗標建置在 32 位 Windows XP 或 Windows Server 2003 上的 32 位應用程式,且具有特殊 /3gb 開機選項最多可以解決 3 GB。 這只會將核心限制為 1 GB,這可能會導致某些驅動程式和/或服務失敗。
在 32 位版本的 Windows Vista、Windows Server 2008 和 Windows 7 上,使用 /LARGEADDRESSAWARE:YES 連結器旗標建置的 32 位應用程式可以解決記憶體,最多可以解決開機設定資料所指定的記憶體, (BCD) 元素 IncreaseUserVa。 IncreaseUserVa 的值範圍介於 2048、預設值為 3072 (,其符合 Windows XP) 上 /3gb 開機選項所設定的記憶體數量。 其餘 4 GB 會配置給核心,並可能導致驅動程式和服務設定失敗。
如需 BCD 的詳細資訊,請參閱 開機設定資料。
64 位平臺上的 32 位應用程式可以處理最多 2 GB,或最多 4 GB,且具有 /LARGEADDRESSAWARE:YES 連結器旗標。
64 位應用程式會使用 43 位進行定址,為應用程式提供 8 TB 的虛擬位址,並為核心保留 8 TB 的虛擬位址。
除了記憶體之外,使用記憶體對應檔案 I/O 的 64 位應用程式可大幅受益于增加的虛擬位址空間。 64 位架構也改善了浮點效能,並更快速地傳遞參數。 六十四位處理器具有兩倍的暫存器數目,包括一般用途和串流 SIMD 擴充功能 (SSE) 類型,以及 SSE 和 SSE2 指令集的支援;許多 64 位處理器甚至支援 SSE3 指令集。
在建置時指定大型位址感知
使用連結器旗標 /LARGEADDRESSAWARE 來建置 32 位應用程式時,最好指定大型位址感知,即使應用程式不是用於 64 位平臺,因為獲得的優點並不付費。 如先前所述,為組建啟用此旗標可讓 32 位程式存取更多記憶體,並在 32 位作業系統或 64 位作業系統上使用特殊開機選項。 不過,開發人員必須小心不要進行指標假設,例如假設高位永遠不會在 32 位指標中設定。 一般而言,啟用 /LARGEADDRESSAWARE 旗標是很好的作法。
具有大型位址感知的三十二位應用程式可以藉由呼叫 GlobalMemoryStatusEx,在執行時間判斷它們可以使用多少虛擬位址空間。 ullTotalVirtual 結果的範圍從 2147352576 個位元組 (2 GB) 到 4 GB) (4294836224 個位元組。 大於 3221094400 (3 GB) 的值只能在 64 位版本的 Windows 上取得。 例如,如果 IncreaseUserVa 的值為 2560,則結果會是 ullTotalVirtual,值為 2684223488 個位元組。
64 位平臺上 32 位應用程式的相容性
64 位 Windows 作業系統與 IA32 架構二進位相容,而 32 位應用程式使用的大多數 API 可透過 Windows 64 位模擬器 WOW64 上的 Windows 32 位取得。 WOW64 有助於確保這些 API 會如預期般運作。
WOW64 有一個執行層,可處理 32 位資料的封送處理。 WOW64 會重新導向 DLL 檔案要求、重新導向 32 位應用程式的一些登錄分支,並反映 32 位和 64 位應用程式的一些登錄分支。
如需 WOW64 的詳細資訊,請參閱 WOW64 實作詳細資料。
潛在的相容性陷阱
針對 32 位平臺開發的大部分應用程式都會執行,而不會在 64 位平臺上發生問題。 一些應用程式可能會發生問題,這可能包括下列各項:
- 64 位版本的 Windows 作業系統的所有驅動程式都必須是 64 位版本。 需要新的 64 位驅動程式對於依賴舊驅動程式的禁止複製配置有影響。 請注意,核心模式驅動程式必須是 Authenticode 簽署,才能由 64 位版本的 Windows 載入。
- 64 位進程無法載入 32 位 DLL,而 32 位進程無法載入 64 位 DLL。 開發人員必須先確定有 64 位版本的協力廠商 DLL 可供使用,才能繼續進行開發。 如果您必須在 64 位進程中使用 32 位 DLL,則可以使用 Windows 處理序間通訊 (IPC) 。 COM 元件也可以使用跨進程伺服器和封送處理在界限之間進行通訊,但這樣做可能會造成效能負面影響。
- 許多 x64 處理器也是多核心處理器,開發人員必須測試這如何影響其繼承應用程式。 如需多核心處理器和遊戲應用程式含意的詳細資訊,請參閱 遊戲計時和多核心處理器。
- 應用程式也應該呼叫 SHGetFolderPath 來探索檔案路徑,因為在某些情況下,某些資料夾名稱已變更。 例如,CSIDL_PROGRAM_FILES會針對在 64 位平臺上執行的 32 位應用程式傳回 「C:\Program Files (x86) 」,而不是 「C:\Program Files」。 開發人員必須留意 WOW64 模擬器的重新導向和反映功能如何運作。
此外,開發人員必須謹慎使用可能仍在使用的 16 位程式。 WOW64 無法處理 16 位應用程式;這包括舊的安裝程式和所有 MS-DOS 程式。
注意
最常見的相容性問題是執行 16 位程式碼的安裝程式,而且沒有 64 位驅動程式來進行禁止複製配置。
下一節討論將程式碼移植到 64 位原生的相關問題,供想要確保舊版程式在 64 位平臺上運作的開發人員。 它也適用于不熟悉 64 位程式設計的開發人員。
將應用程式移植到 64 位平臺
擁有正確的工具和程式庫有助於簡化從 32 位到 64 位開發的轉換。 DirectX 9 SDK 具有程式庫來支援 x86 和 x64 型專案。 Microsoft Visual Studio 2005 和 Visual Studio 2008 同時支援 x86 和 x64 的程式碼產生,而且它們隨附已針對產生 x64 程式碼優化的程式庫。 不過,開發人員也需要將 Visual C 執行時間與其應用程式散發。 請注意,Visual Studio 2005 和 Visual Studio 2008 的 Express 版本不包含 x64 編譯器,但 Standard、Professional 和 Team System 版本全都執行。
以 32 位平臺為目標的開發人員可以準備 64 位開發,以便日後更輕鬆地進行轉換。 編譯 32 位專案時,開發人員應該使用 /Wp64 旗標,這會導致產生會影響可攜性之問題的警告。 一開始,切換至 64 位工具和程式庫可能會產生許多新的組建錯誤;因此,建議您先切換位中性工具和程式庫,並在切換至 64 位組建之前更正任何警告。
不過,變更工具、變更程式庫和使用特定編譯器旗標並不足夠。 必須重新評估程式碼標準中的假設,以確保目前的編碼標準不允許可攜性問題。 可攜性問題可能包括指標截斷、資料類型的大小和對齊方式、依賴 32 位 DLL、使用舊版 API、元件程式碼和舊的二進位檔案。
注意
Visual C++ 2010 或更新版本包含 stdint.h 和 cstdint C99 標頭,其定義標準可攜性類型int32_t、uint32_t、int64_t、uint64_t、intptr_t和uintptr_t。 搭配標準ptrdiff_t和size_t資料類型使用這些專案,可能比較適合下列用來改善程式碼可攜性的 Windows 移植性類型。
主要移植問題包括:
-
指標截斷
-
指標是 64 位 OS 上的 64 位,因此將指標轉換成其他資料類型可能會導致截斷,而指標算術可能會導致損毀。 使用 /Wp64 旗標通常會提供這類問題的警告,但使用多型類型 (INT_PTR、DWORD_PTR、SIZE_T、UINT_PTR等等,在轉型指標類型是協助完全避免此問題的好作法時,) 。 由於指標在新平臺上為 64 位,因此開發人員應該檢查指標的順序,以及類別和結構中的資料類型,以減少或消除填補。
-
資料類型和二進位檔案
-
雖然指標在 64 位平臺上從 32 位增加到 64,但其他資料類型則不會。 固定精確度資料類型 (DWORD32、DWORD64、INT32、INT64、LONG32、LONG64、UINT32、UINT64) 可用於必須知道資料類型大小的位置;例如,在二進位檔案結構中。 指標大小和資料對齊的變更需要特殊處理,以確保 32 位對 64 位相容性。 如需詳細資訊,請參閱 新資料類型。
-
舊版 WIN32 API 和資料對齊
-
某些 WIN32 API 已被取代,並以更中性的 API 呼叫取代,例如 SetWindowLongPtr 取代 SetWindowLong。
在 x64 平臺上,不一致的存取效能會比 x86 平臺上的效能降低更大。 TYPE_ALIGNMENT (t) 和 FIELD_OFFSET (t,成員) 宏可用來判斷程式碼直接使用的對齊資訊。 正確使用這些上述宏應該消除潛在的未對齊存取懲罰。
如需TYPE_ALIGNMENT宏、FIELD_OFFSET宏和一般 64 位程式設計資訊的詳細資訊,請參閱64 位 Windows 程式設計:移轉秘訣:使用指標的其他考慮和規則。
-
元件程式碼
-
64 位平臺上不支援內嵌元件程式碼,且必須加以取代。 架構中的變更可能會變更應用程式瓶頸,而 C/C++ 或內建函式可以透過更容易閱讀的程式碼來達成類似的結果。 建議的做法是將所有元件程式碼切換為 C 或 C++。 內建函式可用來取代元件程式碼,但應該只在執行完整分析和分析之後才使用。
x87、MMX 和 3DNow! 指令集在 64 位模式中已被取代。 32 位模式的回溯相容性仍存在指令集;不過,為了避免未來發生相容性問題,不建議在目前和未來的專案中使用。
-
已被取代的 API
-
64 位原生應用程式已卸載一些較舊的 DirectX API:DirectPlay 4 和更早版本、DirectDraw 6 和更早版本、Direct3D 8 和更早版本,以及 DirectInput 7 和更早版本。 此外,DirectMusic 的核心 API 可供原生 64 位應用程式使用,但效能層和 DirectMusic Producer 已被取代。
Visual Studio 會發出取代警告,而且這些變更不是使用最新 API 的開發人員所發生的問題。
已移植應用程式的分析和優化
所有開發人員都需要重新分析任何要移植到新架構的應用程式。 許多要移植到 64 位平臺的應用程式,其效能設定檔會與其 32 位版本不同。 開發人員必須先執行 64 位效能測試,才能評估需要優化的效能測試。 好消息是許多傳統優化在 64 位平臺上運作。 此外,64 位編譯器也可以使用正確的編譯器旗標和程式碼提示來執行許多優化。
某些結構可能會重新排列其內部資料類型,以節省記憶體空間並改善快取。 在某些情況下,可以使用陣列索引,而不是完整的 64 位指標。 /fp:fast 旗標可以改善浮點優化和向量化。 使用 __restrict,declspec (限制) ,而 declspec (noalias) 可協助編譯器解析別名,並改善暫存器檔案的使用。
如需 /fp:fast 的詳細資訊,請參閱 /fp (指定Floating-Point行為) 。
如需__restrict的詳細資訊,請參閱 Microsoft 特定修飾詞。
如需 declspec (限制) 的詳細資訊,請參閱 優化最佳做法。
如需 declspec (noalias) 的詳細資訊,請參閱 __declspec (noalias) 。
64 位作業系統上的 Managed 程式碼
許多遊戲開發人員在其工具鏈中使用 Managed 程式碼,因此瞭解其在 64 位作業系統上的行為會很有説明。 Managed 程式碼是指令集中性的,因此當您在 64 位作業系統上執行受控應用程式時,Common Language Runtime (CLR) 可以當作 32 位或 64 位進程來執行。 根據預設,CLR 會以 64 位的形式執行受控應用程式,而且它們應該可以正常運作,且不會發生任何問題。 不過,如果您的應用程式相依于原生 32 位的 DLL,則應用程式在嘗試呼叫此 DLL 時將會失敗。 64 位進程需要完全 64 位的程式碼,而且無法從 64 位進程呼叫 32 位 DLL。 最佳的長期解決方案也是將原生程式碼編譯為 64 位,但一個完全合理的短期解決方案是只使用 /platform:x86 組建旗標,將受控應用程式標示為適用于 x86。
執行 64 位作業系統的效能影響
由於具有 AMD64 和 Intel 64 架構的處理器可以原生執行 32 位指令,因此它們可以以完整速度執行 32 位應用程式,即使是在 64 位作業系統上也一樣。 呼叫作業系統函式時,在 32 位和 64 位之間轉換參數的成本相當適中,但此成本通常可忽略。 這表示當您在 64 位作業系統上執行 32 位應用程式時,應該不會看到速度變慢。
當您將應用程式編譯為 64 位時,計算會變得更複雜。 64 位程式使用 64 位指標,其指令稍微大一些,因此記憶體需求會稍微增加。 這可能會導致效能稍微降低。 另一方面,在單一指令中擁有兩倍的暫存器,而且能夠在單一指令中執行 64 位整數計算,通常比補償還要多。 最終結果是,64 位應用程式的執行速度可能會比編譯為 32 位的相同應用程式稍微慢一點,但通常會稍微加快執行速度。
摘要
六十四位架構可讓開發人員推播遊戲外觀、音效和播放方式的限制。 不過,從 32 位程式設計轉換為 64 位程式設計並不簡單。 藉由瞭解這兩者之間的差異,以及使用最新的工具,轉換至 64 位平臺會變得更容易且更快速。
如需 64 位程式設計的詳細資訊,請參閱 Visual C++ 開發人員中心:64 位程式設計。