日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

Unity C# Job System介绍(二) 安全性系统和NativeContainer

發(fā)布時(shí)間:2023/12/13 C# 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Unity C# Job System介绍(二) 安全性系统和NativeContainer 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

C# Job System中的安全性系統(tǒng)

https://docs.unity3d.com/Manual/JobSystemSafetySystem.html?docs.unity3d.com

資源競爭

當(dāng)我們編寫多線程代碼時(shí),經(jīng)常會(huì)有產(chǎn)生資源競爭的風(fēng)險(xiǎn)。資源競爭會(huì)在一項(xiàng)操作的輸出依賴于另一項(xiàng)它掌控之外的操作時(shí)發(fā)生。

資源競爭并不總是視為一個(gè)bug,但它卻是不確定行為發(fā)生的原因之一。當(dāng)資源競爭確實(shí)引發(fā)了一個(gè)bug時(shí),因?yàn)槭桥既话l(fā)生的,因此很難找到問題發(fā)生的確切原因,你只能在偶然情況下才能重現(xiàn)這種問題。調(diào)試時(shí)問題可能就消失了,因?yàn)閿帱c(diǎn)和日志可能改變單個(gè)進(jìn)程的執(zhí)行時(shí)機(jī)。因此資源競爭成為了編寫多線程代碼時(shí)最大的挑戰(zhàn)。

安全性系統(tǒng)

為了讓用戶更容易地編寫多線程代碼,Unity中的C# Job System會(huì)檢測所有潛在的資源競爭,從而避免用戶遇到由此產(chǎn)生的bug

舉例來說:如果C# Job System需要在主線程中發(fā)送一個(gè)數(shù)據(jù)的引用給一個(gè)Job,Job在寫入對(duì)應(yīng)數(shù)據(jù)的時(shí)候無法判斷主線程是否也在同時(shí)操作該數(shù)據(jù)。這種情況下就會(huì)導(dǎo)致資源競爭。

C# Job System通過給每一個(gè)需要操作數(shù)據(jù)的Job一份數(shù)據(jù)的拷貝而不是主線程中數(shù)據(jù)的引用來避免這個(gè)問題。拷貝和原本的數(shù)據(jù)獨(dú)立,從而排除了資源競爭。

C# Job System拷貝數(shù)據(jù)的方式表明了一個(gè)Job只能訪問可以位塊傳輸?shù)臄?shù)據(jù)類型(blitable data types)。這種數(shù)據(jù)類型在托管代碼和原生代碼之間進(jìn)行傳遞的時(shí)候不需要類型轉(zhuǎn)換。

C# Job System可以使用memcpy來拷貝可位塊傳輸數(shù)據(jù),并在Unity的托管部分和原生部分之間傳遞它們。它在安排job時(shí)使用memcpy將數(shù)據(jù)放入原生內(nèi)存,并給予托管部分在job執(zhí)行時(shí)訪問這份拷貝數(shù)據(jù)的接口。查閱更多的信息,查看Scheduling jobs

NativeContainer

https://docs.unity3d.com/Manual/JobSystemNativeContainer.html?docs.unity3d.com

安全性系統(tǒng)中拷貝數(shù)據(jù)的缺點(diǎn)是單個(gè)job的計(jì)算結(jié)果是與外部隔離的。為了突破這個(gè)限制,我們需要把結(jié)果放在一種共享內(nèi)存——NativeContainer中。

什么是NativeContainer?

NativeContainer是一種托管的數(shù)據(jù)類型,為原生內(nèi)存提供一種相對(duì)安全的C#封裝。它包括一個(gè)指向非托管分配內(nèi)存的指針。當(dāng)和Unity C# Job System一起使用時(shí),一個(gè)NativeContainer使得一個(gè)Job可以訪問和主線程共享的數(shù)據(jù),而不是在一份拷貝數(shù)據(jù)上工作。

有什么可用的NativeContainer類型?

Unity使用一個(gè)叫做NativeArray的NativeContainer。你還可以通過一個(gè)NativeSlice來操作一個(gè)NativeArray,從而獲得從某個(gè)特定位置開始確定長度的NativeArray子集。

注意:Entity Component System(ECS)包擴(kuò)展了Unity.Collections命名空間,包括了其他類型的NativeArray:

  • NativeList - 一個(gè)可變長的NativeArray
  • NativeHashMap - 鍵值對(duì)
  • NativeMultiHashMap - 每個(gè)Key可以對(duì)應(yīng)多個(gè)值
  • NativeQueue - 一個(gè)先進(jìn)先出(FIFO)隊(duì)列

NativeContainer和其安全性系統(tǒng)

安全性系統(tǒng)是所有NativeContainer類型的組成部分。它會(huì)追蹤所有關(guān)于任何NaiveContainer的讀寫。

注意:所有關(guān)于NativeContainer類型的安全性檢查(包括下標(biāo)邊界檢查,內(nèi)存釋放檢查和資源競爭檢查),只在Unity Editor和Play Mode中生效。(譯者:即只在編輯器環(huán)境中進(jìn)行檢查)

安全性系統(tǒng)是由DisposeSentinelAtomicSafetyHandle組成的。DisposeSentinel檢測內(nèi)存泄漏同時(shí)在你沒有正確釋放內(nèi)存的時(shí)候給你一個(gè)錯(cuò)誤信息。但內(nèi)存泄漏的錯(cuò)誤只有在泄露發(fā)生很久之后才會(huì)觸發(fā)。

使用AtomicSafetyHandle在代碼中進(jìn)行NativeContainer所有權(quán)的轉(zhuǎn)移。舉例來說,如果兩個(gè)已經(jīng)安排的jobs向同一個(gè)NativeArray寫入數(shù)據(jù),安全性系統(tǒng)會(huì)拋出一個(gè)異常,帶有明確的錯(cuò)誤信息關(guān)于為什么以及如何解決這個(gè)問題。安全性系統(tǒng)會(huì)在你安排一個(gè)違規(guī)的job后拋出一個(gè)異常。

在這種情況下,你可以在安排job的時(shí)候添加一個(gè)依賴。第一個(gè)job可以寫入到NativeContainer,一旦它執(zhí)行完畢,下一個(gè)job可以安全地讀取和寫入同一個(gè)NativeContainer。讀取和寫入的限制同樣影響在訪問主線程中的數(shù)據(jù)時(shí)生效。安全性系統(tǒng)允許多個(gè)jobs并行的讀取同一份數(shù)據(jù)。

通常來說,當(dāng)一個(gè)job有NativeContainer的訪問權(quán)限時(shí),它同時(shí)擁有讀取和寫入的權(quán)限。這種配置會(huì)使性能變差。一個(gè)C# Job System不允許你在有job正在對(duì)一個(gè)NativeContainer進(jìn)行讀寫的時(shí)候,安排另一個(gè)job對(duì)該NaiveContainer擁有寫入權(quán)限。

如果某個(gè)job不需要向某個(gè)NativeContainer寫入,可以將該NativeContainer加上[ReadOnly]屬性,像這樣

[ReadOnly] public NativeArray<int> input;

在上面的例子中,你可以在其他jobs擁有該NativeContainer只讀權(quán)限的時(shí)候同時(shí)執(zhí)行該job。

注意:這邊沒有針對(duì)從一個(gè)job中訪問靜態(tài)數(shù)據(jù)的保護(hù)。訪問靜態(tài)數(shù)據(jù)可以繞過所有的安全性系統(tǒng)并可能導(dǎo)致Unity奔潰。關(guān)于更多的信息,可以查看C# Job System建議和錯(cuò)誤定位

NativeContainer分配器(Allocator)

當(dāng)創(chuàng)建一個(gè)NativeContainer時(shí),你必須指定你需要的內(nèi)存分配類型。分配的類型由jobs運(yùn)行的時(shí)間來決定。這種情況下你可以在每一種情況下使分配器達(dá)到可能的最好性能。

這里對(duì)于NativeContainer的內(nèi)存分配有三個(gè)分配器類型。當(dāng)你初始化你的NativeContainer時(shí)你需要指定一個(gè)合適的分配器。

  • Allocator.Temp是最快的分配類型。它適用于分配一個(gè)生命周期只有一幀或更短時(shí)間的操作。你不應(yīng)當(dāng)把一個(gè)分配器為Temp類型分配的NativeContainer傳遞給jobs使用。你同時(shí)需要在函數(shù)返回之前調(diào)用Dispose方法(例如MonoBehaviour.Update,或者其他從原生到托管代碼的調(diào)用)
  • Allocator.TempJob是相比于Temp是一個(gè)較慢的分配類型但它比Persistent要快。這是一個(gè)生命周期為四幀的內(nèi)存分配而且它是線程安全的。如果你在四幀之內(nèi)沒有調(diào)用Dispose,控制臺(tái)會(huì)打印一個(gè)由原生代碼生成的警告信息。絕大部分小jobs使用這種類型的NativeContainer分配器。
  • Allocator.Persistent是最慢的分配類型但,它可以持續(xù)存在到你需要的時(shí)間,如果必要的話可以貫穿應(yīng)用程序的整個(gè)生命周期。它是直接調(diào)用malloc的一個(gè)封裝。長時(shí)間的jos可以使用這種分配類型。當(dāng)性能比較緊張的時(shí)候你不應(yīng)當(dāng)使用Persistent

使用示例:

NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

注意:上例中的1表明了NativeArray的長度。在這個(gè)例子中,它只有一個(gè)數(shù)組元素(因?yàn)樗辉趓esult中存儲(chǔ)了一塊數(shù)據(jù))。

總結(jié)

以上是生活随笔為你收集整理的Unity C# Job System介绍(二) 安全性系统和NativeContainer的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。