Unity Job System详解(5)——NativeHashSet/Map源码分析

news/2024/11/12 16:14:13/

不再贴完整源码,只贴关键部分源码

需要先看懂C# 字典原理

NativeHashSet的定义为:

public unsafe struct NativeHashSet<T>: INativeDisposable, IEnumerable<T> where T : unmanaged, IEquatable<T>

NativeHashMap的定义为:

public unsafe struct NativeHashMap<TKey, TValue>: INativeDisposable, IEnumerable<KVPair<TKey, TValue>>  where TKey : unmanaged, IEquatable<TKey>  where TValue : unmanaged

比较特殊的是T要求实现IEquatable,如果是int、float等数值类型既然就有,如果是自定义结构体,最好也在自己实现下

两者的核心都在HashMapHelper中,数据在HashMapHelper<T>* m_Data,内存分配同样调用Memory.Unmanaged.Allocate,释放调用Memory.Unmanaged.Free,有依赖释放时会自动创建NativeHashMapDisposeJob,逻辑与NativeList完全一致

与UnsafeList不同的是,这里数据类型不同,没用Block,直接调用的Memory.Unmanaged.Allocate

添加、删除元素,扩容等基本和C#字典相同,使用方式基本相同,不再赘述。

这里不同的是,将value、key、next、bucket按顺序合并在一个数组中了,实现在Init函数中

    internal void Init(int capacity, int sizeOfValueT, int minGrowth, AllocatorManager.AllocatorHandle allocator){Count = 0;Log2MinGrowth = (byte)(32 - math.lzcnt(math.max(1, minGrowth) - 1));capacity = CalcCapacityCeilPow2(capacity);Capacity = capacity;//容量是2的倍数BucketCapacity = GetBucketSize(capacity);//桶数组是2倍容量Allocator = allocator;SizeOfTValue = sizeOfValueT;//value所需内存大小int keyOffset, nextOffset, bucketOffset;int totalSize = CalculateDataSize(capacity, BucketCapacity, sizeOfValueT, out keyOffset, out nextOffset, out bucketOffset);//数组中先是value的数据,其起始地址即为分配的内存的地址Ptr,其大小为valuesSize = sizeOfTValue * capacity; //随后是key的数据,其起始地址为Ptr + valuesSize,其大小为keysSize = sizeOfTKey * capacity;//再后是next的数据,其起始地址为Ptr + valuesSize + keysSize,next的数据是int类型,其大小为nextSize = sizeOfInt * capacity;//最后是bucket的数据,其起始地址为Ptr + valuesSize + keysSize + nextSize,bucket的数据是int类型,其大小为bucketSize = sizeOfInt * bucketCapacity;//四者相加得到所需内存的总大小Ptr = (byte*)Memory.Unmanaged.Allocate(totalSize, JobsUtility.CacheLineSize, allocator);Keys = (TKey*)(Ptr + keyOffset);Next = (int*)(Ptr + nextOffset);Buckets = (int*)(Ptr + bucketOffset);Clear();}

关键的查找如下

    internal int Find(TKey key){if (AllocatedIndex > 0){// First find the slot based on the hashvar bucket = GetBucket(key);//根据Key做Hash计算,得到桶数组索引IDvar entryIdx = Buckets[bucket];//找到当前桶数组的位置所对应的Key数组的链头索引if ((uint)entryIdx < (uint)Capacity){var nextPtrs = Next;while (!UnsafeUtility.ReadArrayElement<TKey>(Keys, entryIdx).Equals(key))//根据Key数组索引值取值,判断是否与传入的key相等{entryIdx = nextPtrs[entryIdx];//Next数组中记录了相同桶数组索引中的key依次的Key数组索引if ((uint)entryIdx >= (uint)Capacity){return -1;}}return entryIdx;}}return -1;//表示没找到}


http://www.ppmy.cn/news/1546076.html

相关文章

gtfToGenePred如何下载

gtfToGenePred 是 UCSC 提供的一款工具&#xff0c;用于将 GTF&#xff08;Gene Transfer Format&#xff09;文件转换为 GenePred 格式的基因注释文件。由于不同的生物信息学分析工具对基因注释文件的格式要求不同&#xff0c;gtfToGenePred 的主要作用就是让 GTF 文件能够兼容…

linux系统中涉及到用户管理的命令知识

用户创建与密码设置 Linux中新建用户使用useradd命令&#xff0c;只有root用户才能执行&#xff0c;若useradd命令直接输入不管用&#xff0c;可使用绝对路径/usr/sbin/useradd。设置用户登录密码使用passwd命令。 su命令相关 su代表switch user&#xff0c;用于切换用户。切换…

开放寻址法、链式哈希数据结构详细解读

一、开放寻址法&#xff08;Open Addressing&#xff09; 1. 定义 开放寻址法是一种哈希冲突解决策略&#xff0c;所有元素都存储在哈希表中。当发生冲突时&#xff0c;即两个键计算出的哈希值相同时&#xff0c;会按照一定的探查序列查找下一个可用的位置来存储新元素。 2.…

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 (二)

【HarmonyOS】鸿蒙应用低功耗蓝牙BLE的使用心得 &#xff08;二&#xff09; 一、前言 目前鸿蒙应用的实现逻辑&#xff0c;基本都是参考和移植Android端来实现。针对BLE低功耗蓝牙来说&#xff0c;在鸿蒙化的实现过程中。我们发现了&#xff0c;鸿蒙独有的优秀点&#xff0c…

机器学习3_支持向量机_线性不可分——MOOC

线性不可分的情况 如果训练样本是线性不可分的&#xff0c;那么上一节问题的是无解的&#xff0c;即不存在 和 满足上面所有N个限制条件。 对于线性不可分的情况&#xff0c;需要适当放松限制条件&#xff0c;使得问题有解。 放松限制条件的基本思路&#xff1a; 对每个训…

Codeforces Round 984 (Div. 3)

题目链接 A. Quintomania 题意 思路 模拟即可 示例代码 void solve() {int n;cin >> n;vector<int>arr(n);fer(i, 0 ,n) cin >> arr[i];fer(i, 1, n){if(abs(arr[i] - arr[i - 1]) ! 5 && abs(arr[i] - arr[i - 1]) ! 7){cout << "N…

信息安全工程师(78)网络安全应急响应技术与常见工具

前言 网络安全应急响应是指为应对网络安全事件&#xff0c;相关人员或组织机构对网络安全事件进行监测、预警、分析、响应和恢复等工作。 一、网络安全应急响应技术 网络安全应急响应组织 构成&#xff1a;网络安全应急响应组织主要由应急领导组和应急技术支撑组构成。领导组负…

跨界码王:21天从产品汪到攻城狮 | 通义灵码和TA的朋友们

本文转自通义灵码用户分享 我是一名产品汪汪经理&#xff0c;常以满腹需求面对程序猿小哥哥小姐姐的冷眼。我在AI师傅实现了Python入门的从0到1&#xff08;其实是到0.5啦~&#xff09;。 从一个从没写通超过十行代码的编程小白&#xff0c;现在跑通了140行代码实现了自己提的需…