Nebula3的多執行緒架構

2021-08-22 20:08:12 字數 2017 閱讀 5093

nebula3的**執行在兩種根本不同的方案中. 第一種方案我稱之為」fat thread」. 乙個fat thread在乙個執行緒中執行乙個完整的子系統(如渲染, 音訊, ai, 物理, 資源管理), 並且基本上鎖定在乙個特定的核心上.

第二種型別的執行緒我叫它」job」. 乙個job是一些資料和用於處理這些資料的包裝成c++物件的**. 工作排程程式掌管了job物件, 並且把工作分配給低負載的核心來保持它們一直處於忙碌狀態.

顯然, 挑戰就是設計乙個經過全面考慮的系統, 以保持所有的核心一直均勻地忙碌著. 這不但意味著連續的活動需要在遊戲每幀的空閒時期內輪流交替, 而且要求job物件不得不事先(如每幀前)建立好, 這樣才能在各種fat thread空閒時填充當前幀的空白.

這是我希望進行更多試驗和調整的地方.

第二個挑戰就是讓程式設計師的工作盡量的簡單. 乙個遊戲應用程式設計師(邏輯程式設計師)在任何時候都不應該關心他執行在乙個多執行緒的環境中, 不應該擔心會產生死鎖或改寫了其它執行緒的資料, 也不應該瞎搞一些臨界區, 事件和訊號量. 同樣, 整個引擎的架構也不應該是」脆弱的」. 大部分傳統的多執行緒**在一定程度上都會發生紊亂, 或者忘記了臨界區而打亂資料.

當執行緒間需要進行資料共享和通訊時, 多執行緒就變得很棘手. 像兩個臨界區這樣的解決方案也會導致脆弱**問題.

從大的角度來說, nebula3通過乙個」並行nebula」的概念解決了這個兩個問題. 其思想就是執行了乙個完整子系統的」fat thread」都有自己的最小nebula執行庫, 這個最小執行庫剛好包含了這個子系統需要的部分. 因此, 如果這個執行在它自己執行緒中的子系統需要進行檔案訪問, 它會有乙個跟其它fat thread完全分離的檔案伺服器(file server). 這個解決方案的優點是, 大部分nebula中的**都不需要知道它執行在乙個多執行緒的環境中, 因為在fat thread之間沒有資料進行共享. 執行著的每個最小nebula核心是跟其它nebula核心完全隔離的. 缺點就是, 重複的資料會浪費一些記憶體, 但是我們只是占用幾kb, 而不是mb.

這些資料冗餘消除了細密的鎖定, 並且解決把程式設計師從思考每一行**的多執行緒安全性中解放了出來.

當然, 從某種意義上說fat thread間的通訊是肯定會發生的, 要不然這整個思想就沒有意義了. 方法就是建立乙個且只有乙個的標準通訊系統, 並且保證這個通訊系統是可靠而快速的. 這就是訊息系統的由來. 要跟乙個fat thread通訊的話只有傳送乙個訊息給它. 訊息是乙個簡單的c++物件, 它包含了一些帶有get/set方法的資料. 通過這個標準的通訊手段, 實際上只有訊息子系統才需要是執行緒安全的(同樣, 訪問跟訊息相關的資源時, 如記憶體緩衝區, 必須受到約束, 因們它們代表了共享資料). (xoyojank: 我說咋那麼多message…)

這樣雖然解決了fat thread方案中大多數的多執行緒問題, 但沒有解決job物件的任何事情. nebula3很有可能需要約束乙個job物件能做什麼和不能做什麼. 最直接的行為就是限制job做記憶體緩衝區的計算. 那樣的話, job中就不能存在複雜的執行庫(不能檔案i/o, 不能訪問渲染等等). 如果這樣還不夠的話, 必須定義乙個」job執行時環境」, 就像fat thread中的那樣. 因為乙個job不會發起它自己的執行緒, 而且還會被排程到乙個已經存在的執行緒池中. 就這個方面來說, 這不存在什麼問題.

到現在為止(xoyojank: 2007/01/21, 最新版本已經實現了多數子系統的多執行緒化), 只有io子系統作為概念證明在fat thread中得到實現, 並且它執行得很今人滿意. 在做傳統的同步io工作時, 乙個nebula3程式可以直接呼叫本地執行緒的io子系統. 所以像列出資料夾的內容或刪除乙個檔案, 只會呼叫乙個簡單的c++方法. 對於非同步io工作, 定義了一些常見的io操作訊息(如readstream, writestream, copyfile, deletefile, 等等). 進行非同步io只需要幾行**: 建立乙個訊息物件, 填充資料, 並傳送這個訊息到乙個iointe***ce單件. 如果必要的話, 這可能會需要等待和輪詢非同步操作.

這樣的好處就是, 整個io子系統沒有一行多執行緒意義上的**, 因為各個在不同的fat thread中的io子系統是完全隔離的(當然, 同步肯定會發生在一些io操作上, 但那都留給作業系統了).

Nebula3中的屬性

attr命名空間下實現了mangalore裡的動態屬性.屬性是編譯期間型別安全的key value對,這是資料庫 database 子系統的基礎.如圖,attrid相於屬性型別,而attributedefinition是屬性型別的定義,其中包含了屬性名,屬性的四位元組碼,值型別和訪問型別 讀 寫 也...

Nebula3的渲染流程

在說流程之前,有必要先看一下n3的frame子系統 每幀的渲染過程都寫進了配置檔案,預設使用的是 frame win32 dx9default.xml 陰影還有另外一套.在frameshader的配置檔案裡,宣告了一些rendertarget,還有framepass和frameposteffect....

Nebula3學習筆記 1 序

前言 目前這個引擎只是乙個預覽版,很多功能仍在開發當中 硬體需求 顯示卡支援shadermodel3.0 作者blog 用到的開源工程 為了避免版本之間的不相容,已經在sdk中包含 體系結構一覽 nebula3 會跟mangalore 合為乙個整體,mangalore的各種子系統會整合到nebula...