Unity C# Job System 官方文檔翻譯(Base Unity2019.3)三-NativeContainer

NativeContainer

        安全系統複製數據過程的缺點在於,它還會隔離每個副本中的Job結果。爲了克服此限制,您需要將結果存儲在一種稱爲NativeContainer的共享內存中(所謂共享的意思是主線程和各個Job都能訪問)。

       關於NativeContainer,unity有代碼級的文檔,https://docs.unity3d.com/ScriptReference/Unity.Collections.LowLevel.Unsafe.NativeContainerAttribute.html
建議先看本文,先了解概念,再看代碼級的文檔。

什麼是NativeContainer?

NativeContainer是一種託管值類型,爲本地內存提供相對安全的C#包裝器(wrapper)。它包含一個指向非託管分配的指針。與Unity C#作業系統一起使用時,NativeContainer允許Job訪問與主線程共享的數據,而不是使用副本。【個人覺得是爲了性能,認同的點贊

可用的NativeContainer類型是什麼?

Unity附帶了一個NativeContainer稱爲NativeArray的東西。您還可以NativeArray使用NativeSlice操縱,以NativeArray從特定位置到特定長度獲取的子集。

注意:ECS包擴展了Unity.Collections名稱空間,以包括其他類型的NativeContainer:

  • NativeList-可調整大小NativeArray。
  • NativeHashMap -鍵和值對。
  • NativeMultiHashMap -每個鍵有多個值。
  • NativeQueue- 先進先出(FIFO)隊列。
  • NativeContainer和安全系統

安全系統內置於所有NativeContainer類型中。它跟蹤對任何對象的讀寫操作NativeContainer。

注意:所有關於NativeContainer類型的安全檢查(例如越界檢查,解除分配檢查和競爭條件檢查)僅在Unity Editor和Play Mode中可用。

此安全系統的一部分是DisposeSentinel和AtomicSafetyHandle。DisposeSentinel如果沒有正確釋放內存,檢測到內存泄漏並給您一個錯誤。觸發內存泄漏錯誤發生在泄漏發生很長時間之後。

使用AtomicSafetyHandle來轉移NativeContainerin代碼的所有權。例如,如果兩個安排的Job正在寫入同一作業NativeArray,則安全系統將引發異常,並顯示一條清晰的錯誤消息,以解釋原因以及如何解決該問題。當您安排(schedule)有問題的Job時,安全系統將引發此異常。

在這種情況下,您可以安排具有依賴項的Job。第一個作業可以寫入NativeContainer,一旦完成執行,下一個Job就可以安全地對其進行讀寫NativeContainer。從主線程訪問數據時,讀取和寫入限制也適用。安全系統確實允許多個Job並行地從同一數據讀取。

默認情況下,當Job對NativeContainer有權訪問時,它同時具有讀和寫訪問權限。此配置可能會降低性能。C#Job System不允許您同時安排(schedule)兩個Job,其兩個Job都對同一個NativeContainer寫入訪問權限。

如果Job不需要寫入NativeContainer,請用[ReadOnly]屬性標記,如下所示:

[ReadOnly]
public NativeArray<int> input;

在上面的示例中,您可以與其他同時執行的Job只讀訪問NativeArray。

注意:無法防止從Job內部訪問靜態數據。訪問靜態數據會繞過所有安全系統,並可能使Unity崩潰。有關更多信息,請參見《C#Job System提示和故障排除》。

NativeContainer內存分配器

創建NativeContainer,必須指定所需的內存分配類型。分配類型取決於Job運行的時間長短。這樣,您可以調整分配器以在每種情況下獲得最佳性能。NativeContainer有三種用於內存分配和釋放的內存分配器(Allocator)。當實例化NativeContainer,需要指定適當的一個。

  • Allocator.Temp
    分配最快。它用於壽命不超過一幀的分配。您不應該將NativeContainer分配使用傳遞Temp給作業。Dispose從方法調用返回之前,還需要先調用該方法(例如MonoBehaviour.Update或從本機代碼到託管代碼的任何其他回調)。
  • Allocator.TempJob
    分配Temp速度比慢,但比快Persistent。它用於在四個幀的生命週期內進行分配,並且是線程安全的。如果Dispose在四幀之內沒有收到警告,則控制檯會輸出一條從本機代碼生成的警告。大多數小型Job使用此分配類型。
  • Allocator.Persistent
    是最慢的分配,但是可以持續到您需要的時間,並且在整個應用程序的生命週期中(如果需要)。它是直接調用malloc的包裝。較長的Job可以使用此分配類型。您不應在性能至關重要的地方使用Persistent

    舉個栗子
     
  • NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

    注意:上例中的數字1表示NativeArray的大小。在這種情況下,它只有一個數組元素(因爲它僅在result中存儲一個數據)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章