遊戲計時與多核心處理器
隨著現今電腦中的電源管理技術變得更常見,常用的方法來取得高解析度 CPU 計時,RDTSC 指令可能無法再如預期般運作。 本文建議使用 Windows API QueryPerformanceCounter 和 QueryPerformanceFrequency取得高解析度 CPU 計時的更精確可靠解決方案。
背景
由於引進 x86 P5 指令集,許多遊戲開發人員都已使用讀取時間戳記計數器 RDTSC 指令來執行高解析度計時。 Windows 多媒體計時器精確到足以處理音效和視訊,但畫面時間超過十毫秒或更少,它們沒有足夠的解析度可提供差異時間資訊。 許多遊戲仍會在啟動時使用多媒體計時器來建立 CPU 的頻率,並使用該頻率值來調整 RDTSC 的結果,以取得精確的時間。 由於 RDTSC 的限制,Windows API 會透過 QueryPerformanceCounter 和 QueryPerformanceFrequency常式公開更正確的方式來存取這項功能。
使用 RDTSC 進行計時時發生下列基本問題:
- 不連續的值。 直接使用 RDTSC 會假設執行緒一律在相同的處理器上執行。 多處理器和雙核心系統不保證其迴圈計數器在核心之間同步處理。 這在與在不同時間閒置和還原各種核心的新式電源管理技術結合時,這會造成核心通常無法同步處理時。 對於應用程式,這通常會導致問題或潛在的當機,因為執行緒在處理器之間跳躍,並取得導致大型差異、負差異或停止計時的計時值。
- 專用硬體的可用性。 RDTSC 會鎖定應用程式向處理器迴圈計數器要求的時間資訊。 多年來,這是取得高精確度計時資訊的最佳方式,但較新的主機板現在包含專用計時裝置,可提供高解析度計時資訊,而不會有 RDTSC 的缺點。
- CPU 頻率的變化性。 假設通常會在程式生命週期中固定 CPU 的頻率。 不過,使用現代化電源管理技術時,這是不正確的假設。 雖然一開始僅限於膝上型電腦和其他行動裝置,但變更 CPU 頻率的技術在許多高階桌上型電腦中使用;停用其函式以維持一致的頻率,通常使用者無法接受。
建議
遊戲需要精確的計時資訊,但您也需要以避免使用 RDTSC 相關問題的方式實作計時程式碼。 當您實作高解析度計時時,請採取下列步驟:
使用 QueryPerformanceCounter 和 QueryPerformanceFrequency ,而不是 RDTSC。 這些 API 可能會使用 RDTSC,但可能會改用主機板上的計時裝置,或提供高品質高解析度計時資訊的一些其他系統服務。 雖然 RDTSC 比 QueryPerformanceCounter快很多,因為後者是 API 呼叫,但它是每個畫面可以呼叫數百次的 API,而不會有任何明顯的影響。 不過, (,開發人員應該盡可能嘗試讓其遊戲呼叫 QueryPerformanceCounter ,以避免任何效能損失。)
計算差異時,應該限制這些值,以確保計時值中的任何 Bug 都不會造成當機或不穩定的時間相關計算。 限制範圍應從 0 (,以防止負差異值) 根據您的預期畫面播放速率,達到一些合理的值。 在應用程式的任何偵錯中,限制可能很有用,但如果執行效能分析或在一些未優化模式中執行遊戲,請務必記住它。
計算單一線程上的所有計時。 在多個執行緒上計算計時,例如,與特定處理器相關聯的每個執行緒,可大幅降低多核心系統的效能。
使用 Windows API SetThreadAffinityMask,將該單一線程設定為保留在單一處理器上。 一般而言,這是主要遊戲執行緒。 雖然 QueryPerformanceCounter 和 QueryPerformanceFrequency 通常會針對多個處理器進行調整,但 BIOS 或驅動程式中的 Bug 可能會導致這些常式傳回不同的值,因為執行緒從一個處理器移到另一個處理器。 因此,最好讓執行緒保持在單一處理器上。
所有其他執行緒都應該運作,而不需收集自己的計時器資料。 我們不建議使用背景工作執行緒來計算時間,因為這會成為同步處理瓶頸。 相反地,背景工作執行緒應該從主執行緒讀取時間戳記,因為背景工作執行緒只會讀取時間戳記,所以不需要使用重要區段。
只呼叫 QueryPerformanceFrequency 一次,因為系統執行時頻率不會變更。
應用程式相容性
許多開發人員已假設 RDTSC 在數年的行為,因此,由於計時實作,某些現有應用程式可能會在具有多個處理器或核心的系統上執行時顯示問題。 這些問題通常會顯示為問題或緩慢動作移動。 對於不知道電源管理的應用程式,並沒有簡單的補救方法,但有一個現有的填充碼,可強制應用程式一律在多處理器系統中的單一處理器上執行。
若要建立此填充碼,請從 Windows 應用程式相容性下載 Microsoft 應用程式相容性工具組。
使用工具組的相容性系統管理員,建立應用程式的資料庫和相關修正程式。 為此資料庫建立新的相容性模式,並選取相容性修正 SingleProcAffinity ,強制應用程式的所有線程在單一處理器/核心上執行。 藉由使用命令列工具Fixpack.exe (工具組) 的一部分,您可以將此資料庫轉換成可安裝的套件,以進行安裝、測試和散發。
如需使用相容性系統管理員的指示,請參閱工具組的檔。 如需使用 Fixpack.exe 的語法和範例,請參閱其命令列說明。
如需客戶導向的資訊,請參閱 Microsoft 說明及支援中的下列知識庫文章:
- 使用 QueryPerformanceCounter 函式的程式可能會在 Windows Server 2003 和 Windows XP (文章 895980) 中執行效能不佳