JobSystem 的 IJobParallelFor 使用
发布日期:2021-05-20 02:22:50 浏览次数:25 分类:精选文章

本文共 2558 字,大约阅读时间需要 8 分钟。

IJobParallelFor 的作用原理解:

IJob 一次只能执行单独的任务,如果需要反复执行某个操作多次,就功能上需要使用 ParallelFor 的功能。ParallelFor 却允许将任务拆分成多个并行运行的子任务,每次只处理数据源的一个独立部分。

ParallelFor jobs 通常使用 NativeArray 作为数据源,并能分配执行任务到多个 CPU 核心上。每个 job 都只负责处理完整数据的一个子集。当调用 Execute 方法时,框架会自动为数据源中的每个项目调用一次。

需要手动指定执行次数,通常直接取 NativeArray 的长度作为 executors 的数量,每个 executor 处理一个数据项。一个 job 在执行过程中,如果某个批处理提前完成,就会从其他 job 中拿取剩余的批处理继续执行。

关于粒度问题:

任务粒度太细会导致频繁的新 task 创建开销增加。而粒度过粗又会使 singlethreaded 的负载压力增大。一般来说,应从最小粒度1开始逐步增加,直到性能达到顶峰为止。

注意事项:

  • 避免在 job 中访问 static 数据。因为 static 数据可能被多个 job 共享,会导致竞态条件。

  • Explicitly Flush scheduled batches。如果不调用 JobHandle.Complete(),调度逻辑将会被挂起等待 batch 执行结果完成才能继续。

  • 不要试图直接修改 NativeContainer 的内容。如NativeArray[0]++ 这样的操作必须通过 Framework 提供的 API 执行,否则可能导致内存泄漏或逻辑错误。

  • 在主线程中使用 Schedule 和 Complete 函数。不要在 job 依赖关系中使用前 job 中手动 schedule 后 job。

  • 调用 Schedule 和 Complete 必须在正确的时机进行。Schedule 要在数据填充完毕后立即调用,Complete 则只在获取结果时才调用。

  • 配合正确的使用 Schedule 和 Complete 方法。Schedule 方法实现了 «fire and forget» 模式,一旦调用就立即执行任务,无需等待结果。而 Complete 方法则是只在需要访问结果的时候使用,确保数据已经计算完成。

  • 尽可能用读-only 对应 NativeArray。要是确认只需要读取数据的话,可以在初始化时标记为 read-only,这样可以提高性能。

  • 不要在 Job 中使用托管内存分配。Job 内部的代码应该都避免使用 new 语句或者 GCpravітиve allocate。如果需要,应尽量使用 不可变的数据结构。

  • 代码示例优化:

    using System.Collections;
    using System.Collections.Generic;
    using Unity.Collections;
    using Unity.Jobs;
    using UnityEngine;
    using UnityEditor;
    public class TestJobParallelFor_1 : MonoBehaviour
    {
    public struct MyParallelJob : IJobParallelFor
    {
    public NativeArray
    a;
    public NativeArray
    b;
    public NativeArray
    result;
    public void Execute(int index)
    {
    result[index] = a[index] + b[index];
    }
    }
    // 调度并执行并行任务
    void ScheduleParallelJob()
    {
    NativeArray
    a = new NativeArray
    (10, Allocator.TempJob);
    NativeArray
    b = new NativeArray
    (10, Allocator.TempJob); NativeArray
    result = new NativeArray
    (10, Allocator.TempJob); for (int i = 0; i < 10; i++) { a[i] = i * 0.3f; b[i] = i * 0.5f; } var jobData = new MyParallelJob(); jobData.a = a; jobData.b = b; jobData.result = result; // 执行并行任务 var handle = jobData.Schedule(10, 1); // 等待任务完成 handle.Complete(); // 检查结果 for (int i = 0; i < 10; i++) { Debug.LogError("Result at index " + i + ": " + result[i]); } // 配态 a.Dispose(); b.Dispose(); result.Dispose(); } // 在每帧更新时触发任务调度 private void Update() { ScheduleParallelJob(); } }

    需要注意的关键点总结:

  • IJobParallelFor 解决多次重复任务的性能问题;
  • data processing 通过并行架构分摊计算压力;
  • 调度方式需谨慎处理,以避免阻塞主线程;
  • 内存使用需遵循指南,防留垃圾 collector 不必要的负担;
  • 读写数据操作需要膳胃于分配机制。
  • 上一篇:内存管理之垃圾回收
    下一篇:JobSystem 基本概念&IJob使用

    发表评论

    最新留言

    做的很好,不错不错
    [***.243.131.199]2025年04月30日 14时33分03秒