Version: 2022.3

IJobParallelFor

interface in Unity.Jobs

切换到手册

描述

Parallel-for 作业允许对原生容器的每个元素或对于固定的迭代次数执行相同的独立操作。

安排作业后,系统将针对多个并行工作线程调用作业的 Execute(int index) 方法。

对于从 0 到给定长度的每个索引,系统将分别执行一次 Execute(int index)。 每个迭代必须独立于其他迭代(安全系统会为您强制执行此规则)。这些索引没有确定的顺序,而是在多个核心上并行执行。

Unity 会自动将工作拆分为不小于所提供 batchSize 的块,并根据工作线程数、数组长度和批次大小安排适当数量的作业。

批次大小通常应根据作业中执行的工作量来选择。简单作业(例如互相添加一些 Vector3)的批次大小应为 32 到 128。但是,如果执行的工作涉及十分高昂的成本,那么最好使用较小的批次大小;对于高成本工作,完全可以将批次大小设置为 1。IJobParallelFor 使用原子操作执行工作窃取。批次大小可能较小,但并不免费。

返回的 JobHandle 可用于确保作业已完成。它也可以作为依赖项传递给其他作业,从而确保作业在工作线程中逐个执行。

using UnityEngine;
using Unity.Collections;
using Unity.Jobs;

class ApplyVelocityParallelForSample : MonoBehaviour { struct VelocityJob : IJobParallelFor { // Jobs declare all data that will be accessed in the job // By declaring it as read only, multiple jobs are allowed to access the data in parallel [ReadOnly] public NativeArray<Vector3> velocity;

// By default containers are assumed to be read &amp; write public NativeArray<Vector3> position;

// Delta time must be copied to the job since jobs generally don't have concept of a frame. // The main thread waits for the job same frame or next frame, but the job should do work deterministically // independent on when the job happens to run on the worker threads. public float deltaTime;

// The code actually running on the job public void Execute(int i) { // Move the positions based on delta time and velocity position[i] = position[i] + velocity[i] * deltaTime; } }

public void Update() { var position = new NativeArray<Vector3>(500, Allocator.Persistent);

var velocity = new NativeArray<Vector3>(500, Allocator.Persistent); for (var i = 0; i < velocity.Length; i++) velocity[i] = new Vector3(0, 10, 0);

// Initialize the job data var job = new VelocityJob() { deltaTime = Time.deltaTime, position = position, velocity = velocity };

// Schedule a parallel-for job. First parameter is how many for-each iterations to perform. // The second parameter is the batch size, // essentially the no-overhead innerloop that just invokes Execute(i) in a loop. // When there is a lot of work in each iteration then a value of 1 can be sensible. // When there is very little work values of 32 or 64 can make sense. JobHandle jobHandle = job.Schedule(position.Length, 64);

// Ensure the job has completed. // It is not recommended to Complete a job immediately, // since that reduces the chance of having other jobs run in parallel with this one. // You optimally want to schedule a job early in a frame and then wait for it later in the frame. jobHandle.Complete();

Debug.Log(job.position[0]);

// Native arrays must be disposed manually. position.Dispose(); velocity.Dispose(); } }

公共函数

Execute实现此方法以针对特定迭代索引执行工作。