unity 之 Job system

Unity 的 C# Job System 提供了一种管理多线程代码的方法,通过 Worker threads 在 CPU 内核上执行 Jobs,以提高性能并减少资源争用。Jobs 是执行特定任务的小单元,可以依赖其他 Jobs 以处理复杂任务。Job System 通过安全系统避免竞争条件,使用 NativeContainer 允许 Jobs 与主线程共享数据。开发者需要注意不要在 Jobs 中访问静态数据,使用 Schedule 和 Complete 管理 Jobs,并利用 JobHandle 处理依赖。ParallelFor Jobs 则用于并行处理大量对象,通过 Index 参数指定处理数据的子集。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C# Job System Overview

How the C# Job System works

The Unity C# Job System 允许用户编写 multithreaded code

多线程可以提供高性能。包括帧率的显著提高。c# job system(记住了这里是c#的job  system)和Burst编译器一起使用可以提高代码生成质量,这也可以显著降低移动设备上的电池消耗。

它集成了Unity的中Job System,这种协作避免了创建比CPU内核更多的线程(创建的线程比内核多会导致对CPU资源的争用)。

What is multithreading?

在单线程计算系统中,一次输入一条指令,一次输出一个结果。CPU加载和完成程序的时间取决于需要完成的工作量。

多线程是一种编程类型,它利用CPU的能力在多核之间同时处理多个线程。它们不是一个接一个地执行任务或指令,而是同时运行

默认情况下,在程序开始的时候运行线程。成为“主线程”。主线程创建新线程来处理任务。这些新线程彼此并行运行,并且通常在完成后将其结果与主线程同步。

如果您有一些任务需要长时间运行,那么这种多线程方法可以很好地工作。然而,游戏开发代码通常包含许多需要同时执行的小指令。如果您为每个任务创建一个线程,您可能会得到许多线程,每个线程的生命周期都很短。这可能会使CPU和操作系统的处理能力达到极限。

当然可以通过拥有一个线程池,可以减轻线程生存期的问题。但是,即使使用线程池,也可能有大量线程同时处于活动状态. 拥有比CPU内核更多的线程会导致线程之间争夺CPU资源,从而导致频繁的上下文切换(先保存当前线程的部分状态,然后重新构造一个线程,用上个线程的状态继续处理它。上下文切换是资源密集型的,所以应该尽可能避免使用它)。

What is a job system?

 Job system 通过创建jobs而不是线程来管理多线程 multithreaded code

 Job system 通过CPU的多核来管理工作线程 worker threads .通常在每个CPU内核上有一个工作线程,以避免上下文切换(尽管它可能为操作系统或其他专用应用程序保留一些内核)。

Job system 把jobs 放在job queue 执行. Job system中的Worker threads从  job queue 队列里取出,然后执行执行它

也就是 Job System包含多个workerthread(取决于cpu内核的数量),workerthread 从job queue里面取job  执行,workerthread可以执行很多job,而不是每一个job单独一个workerthread

What is a job?

Job 是工作的一个小单位,做一个特定的任务.  Job接收参数并对数据进行操作,类似于方法调用的行为. Job 可以独立工作,也可以依赖其它Jobs来完成工作

What are job dependencies?

在复杂的系统中,比如游戏开发所需要的系统,每个任务都不可能是独立的.  一个Job 通常是为下一个Job准备数据.如果 jobA 依赖jobB, the job system 确保 jobA在jobB 完成之前不会执行,减少竞争关系

 

The safety system in the C# Job System

Race conditions

当使用多线程时, 总会有资源竞用的风险(多个线程同时操作同一组数据). 当一个操作的输出结果依赖于其控制范围之外的另一个进程的处理结果时,就会出现竞争条件

竞态条件并不总是一个bug,但它是不确定性行为的一个来源. 当竞态条件确实导致bug时,可能很难找到问题的根源,因为它依赖于时间,因此,您只能在极少数情况下重新创建该问题. 调试它可能会导致问题消失,因为断点和日志记录可能会改变各个线程的计时. 竞争条件在编写多线程代码时产生了最大的挑战.

Safety system

Unity C# Job System 检测所有潜在的竞争条件,并保护你免受他们可能造成的错误。

比如:  C# Job System从主线程中给job发送一个对数据的引用时,它无法验证主线程在读取数据的同时Job是否正在向其写入数据, 这就会造成一个 race condition.

C# Job System通过把它需要操作的数据复制一份,来解决这种问题,而不是直接引用主线程中数据. 该副本隔离了原始数据,消除了竞争条件

C# Job System复制数据的方式意味着job只能访问  blittable(托管代码和非托管代码之间是等价的,不用做相应的转换,比如int,在c#和c++里面都是int类型)  类型的数据 data types. 在托管代码和本机代码之间传递时,这些类型不需要转换

C# Job System 可以通过memcpy方式拷贝 blittable types 类型,并在托管和unity的本机代码之间传送数据. 它使用内存拷贝的方式 memcpy(也就是另辟一块内存存放拷贝的值),然后通过调度job对它操作,然后允许托管端访问该副本 see Scheduling jobs.

NativeContainer

 safety system的缺点就是单独对拷贝数据进行操作的同时,也导致了操作结果的隔离,也就是job的结果和main thread中的结果不一致了. 为了解决这个问题,你需要把结果存储在一个名为NativeContainer共享内存里面。

What is a NativeContainer?

NativeContainer 是托管值类型,为非托管内存(也就是c++用的内存)提供一个相对安全的c#包装器. 它包含一个指向非托管分配内存的指针,这样操作的就是同一块内存了,job和main thread中的数据就一致了,当使用 Unity C# Job System时,  NativeContainer 允许job 访问与主线程共享的数据,而不是使用副本,但是这只是访问,而不是写入,写入是存在竞争关系的。

What types of NativeContainer are available?

Unity 创建了一个基本的 NativeContainer 叫做 NativeArray.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TO_ZRG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值