游戲AI(二)—行為樹優化之記憶體優化

来源:http://www.cnblogs.com/moonmagician/archive/2017/12/24/8099327.html
-Advertisement-
Play Games

上一篇我們講到了AI架構之一的行為樹,本篇文章和下一篇文章我們將對行為樹進行優化,在本篇文章中我們講到的是記憶體優化 問題 上一篇中我們設計的行為樹由於直接採用new進行動態記憶體分配,沒有自己進行管理。因此行為樹各節點的存儲位置會散佈在記憶體空間的各處,行為樹在不同節點中切換時會導致Cache頻繁失效。 ...


上一篇我們講到了AI架構之一的行為樹,本篇文章和下一篇文章我們將對行為樹進行優化,在本篇文章中我們講到的是記憶體優化

問題

上一篇中我們設計的行為樹由於直接採用new進行動態記憶體分配,沒有自己進行管理。因此行為樹各節點的存儲位置會散佈在記憶體空間的各處,行為樹在不同節點中切換時會導致Cache頻繁失效。
通過記憶體管理改變行為樹節點的記憶體分佈,可以顯著提高行為樹的記憶體性能。

解決辦法

我們可以在BehaviorTree中引入一組記憶體分配的API來保證各節點儘量分配在連續的記憶體上,代碼如下

BehaviorTree(Behavior*InRoot):Root(InRoot),
Buffer(new uint8_t[MaxBehaviorTreeMemory]),Offset(0){}
~BehaviorTree(){ delete[] Buffer; }
    
template<typename T>
        T* Allocate()
        {
            T* Node = new((void*)((uintptr_t)Buffer + Offset)) T;
            Offset += sizeof(T);
            assert(Offset < MaxBehaviorTreeMemory);
            return Node;
        }

我們在BehaviorTree中引入一個Allocate函數用來負責所有節點的記憶體分配。
當行為樹被構造時,一塊用於保存節點的記憶體空間Bufffer會隨之分配,Allocate函數通過Placement new在Buffer上進行記憶體分配,通過Offset記錄分配已分配記憶體的偏移地址。
通過這種方式我們可以讓節點分配在連續的記憶體上,同時通過控制分配節點的順序(如深度遍歷廣度遍歷等),我們可以進一步減少行為樹遍歷時產生的Cache失效,提高記憶體性能。)

複合節點

除了對節點分配進行優化,我們還可以改變複合節點的記憶體佈局,進一步提升性能。

class Composite :public Behavior
    {
    public:
        friend class BehaviorTree;
        virtual void AddChild(Behavior* InChild) override
        { 
            assert(ChildrenCount < MaxChildrenPerComposite);
            ptrdiff_t p = (uintptr_t)InChild - (uintptr_t)this;
            assert(p < std::numeric_limits<uint16_t>::max());
            Children[ChildrenCount++] = static_cast<uint16_t>(p);
        }   

        Behavior* GetChild(size_t index)
        {
            assert(index < MaxChildrenPerComposite);
            return (Behavior*)((uintptr_t)this + Children[index]);
        }

        size_t GetChildrenCount()
        {
            return ChildrenCount;
        }

protected:
        uint16_t Children[MaxChildrenPerComposite];
        uint16_t ChildrenCount = 0;
    };

在如上代碼中,我們通過靜態數組代替vector,避免在存儲時vector所產生的額外堆操作,通過用保存子節點相對於複合節點的偏移地址來代替直接保存子節點指針以節省記憶體空間。由於更換了子節點的存儲方式,我們需要通過getchild()函數來根據複合節點地址和子節點偏移地址獲得子節點指針。

總結

以上,就是關於行為樹的記憶體優化方式,當然凡事無絕對,究竟如何構造行為樹應當根據實際情況選擇,下一篇我們將講述另一種行為樹優化方法。
[gihub鏈接][1]


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 架構的核心就是 交互,而實現這個交互的前提是弄清楚H5和Native端的交互 本文主要介紹Native端(Android/iOS)和H5端(泛指前端)的交互原理 (之前也整理過類似的文章,本系列重新梳理) 與`H5`交互的兩種方式 原生和前端的交互有兩種方式: 以及 (在Android中是 ) ...
  • jquery中ajax請求後臺數據成功後既不執行success也不執行error,此外系統報錯:Uncaught SyntaxError: Unexpected identifier at Object.success,但後臺能夠返回數據,原代碼如下: 主要原因在於後臺返回的數據並非json格式,而 ...
  • 國際化環境下系統架構演化資料庫架構Related Link:JFrog Artifactory https://jfrog.com/open-source/Ansible http://www.ansible.com.cn/index.htmlgrafana https://grafana.com/... ...
  • 線上聊天項目結構圖: 多用戶登陸效果圖: 多用戶聊天效果圖: 資料庫效果圖: 重新構建了Server類,使用了Gson方法,通過解析Json字元串,增加Info類,簡化判斷過程。 Server類代碼如下: 新增的工具類Info,通過info對象的get方法把獲得服務端得到的各種字元串直接歸類了。 I ...
  • java二分查找法 今晚上在逛碼雲的時候,看到一個php的二分查找法,看著這詞比較熟悉,(因為當時學php的時候也學過,只是工作中沒用過,又加上學的時候就稀里糊塗的,慢慢的就忘了),就點進去了,就用java寫了一遍,使用的遞歸。 二分查找法的個人理解: 首先你得是個從小到大順序的數組,進行數組索引取 ...
  • 建模的重要性: 為了更好的理解一個系統 管理複雜度(也就是為了敏捷開發) 理解不同的關註點 儘早發現問題和遺漏 與項目干係人進行溝通 驅動實現 資源高效利用 ...
  • 簡單聊天Demo 使用tcp協議實現的簡單聊天功能(非常簡單的) 思想:使用2個線程,一個線程是用來接收消息的,另一個線程是用來發消息的。 客戶端Demo代碼: 伺服器端Demo代碼: 發送線程的Demo代碼: 接收線程的Demo代碼: ...
  • 今天的學習內容是python中的列表的相關內容。 一.創建列表 1.創建一個普通列表 2.創建一個混合列表 3.創建一個空列表 三種方式就介紹給大家了,接下來,如果想向列表中添加元素,該怎麼辦呢? 二.向列表中添加元素 1.append >>> tabulation1.append('紫霞')>>> ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...