Search Unity

How to pass Array/Lists to a IJobParallelFor job?

Discussion in 'Entity Component System' started by whiskers434, Dec 28, 2019.

  1. whiskers434

    whiskers434

    Joined:
    Sep 23, 2014
    Posts:
    28
    Hi,

    How does one correctly pass a list of lists to a parallel for job to be used by each parallel?

    Seeing as you can't have structs containing native collections or have 2d native collections or am i just missing something?

    Below is just a sample job to show my problem, trying to pass an array of structs containing an array to the parallel job, but if I do that i get some error about its not bitable or something

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Collections;
    4. using Unity.Jobs;
    5. using UnityEngine;
    6.  
    7. public class TestJobScript : MonoBehaviour
    8. {
    9.     [System.Serializable]
    10.     struct JobValues
    11.     {
    12.         public int value;
    13.         public int other_value;
    14.         public NativeArray<MoreValues> more_values_array;
    15.     }
    16.  
    17.     [System.Serializable]
    18.     struct MoreValues
    19.     {
    20.         public int value;
    21.         public int other_value;
    22.  
    23.         public MoreValues(int value, int other_value)
    24.         {
    25.             this.value = value;
    26.             this.other_value = other_value;
    27.         }
    28.     }
    29.  
    30.     [System.Serializable]
    31.     struct JobResult
    32.     {
    33.         public int result;
    34.         public int other_result;
    35.  
    36.         public JobResult(int result, int other_result)
    37.         {
    38.             this.result = result;
    39.             this.other_result = other_result;
    40.         }
    41.     }
    42.  
    43.  
    44.     SampleParallelJob sample_job;
    45.     JobHandle job_handle;
    46.     NativeArray<JobValues> job_values;
    47.     NativeMultiHashMap<int, JobResult> job_results;
    48.  
    49.     void SampleJob()
    50.     {
    51.         //set up
    52.         job_values = new NativeArray<JobValues>(10, Allocator.TempJob);
    53.         job_results = new NativeMultiHashMap<int, JobResult>(10 * 10, Allocator.TempJob);
    54.  
    55.         //get the data
    56.         for (int i = 0; i < 10; i++)
    57.         {
    58.             var values = new JobValues();
    59.             values.value = 1;
    60.             values.other_value = 10;
    61.             values.more_values_array = new NativeArray<MoreValues>(10, Allocator.TempJob);
    62.  
    63.             for (int j = 0; j < 10; j++)
    64.             {
    65.                 values.more_values_array[j] = new MoreValues(1,2);
    66.             }
    67.  
    68.             job_values[i] = values;
    69.         }
    70.  
    71.         //create the job
    72.         sample_job = new SampleParallelJob();
    73.         sample_job.job_values = job_values;
    74.         sample_job.job_results = job_results.ToConcurrent();
    75.  
    76.         //start job
    77.         job_handle = sample_job.Schedule(job_values.Length, 1);
    78.  
    79.         //job complete
    80.         job_handle.Complete();
    81.  
    82.         //handle results
    83.         var results = job_results.GetValueArray(Allocator.Temp);
    84.         for (int i = 0; i < results.Length; i++)
    85.         {
    86.             var temp = results[i].result;
    87.             //process results etc...
    88.         }
    89.  
    90.         //clean up
    91.         results.Dispose();
    92.         job_values.Dispose();
    93.         job_results.Dispose();
    94.     }
    95.  
    96.     struct SampleParallelJob : IJobParallelFor
    97.     {
    98.         [ReadOnly]
    99.         public NativeArray<JobValues> job_values;
    100.  
    101.         [WriteOnly]
    102.         public NativeMultiHashMap<int, JobResult>.Concurrent job_results;
    103.  
    104.         public void Execute(int index)
    105.         {
    106.             var job_value = job_values[index];
    107.  
    108.             for (int i = 0; i < 10; i++)
    109.             {
    110.                 var result = job_value.more_values_array[i].other_value;
    111.                 var other_result = job_value.more_values_array[i].value;
    112.                 job_results.Add(index, new JobResult(result, other_result));
    113.  
    114.             }
    115.  
    116.             job_value.more_values_array.Dispose();
    117.         }
    118.     }
    119. }
    120.  
     
  2. Soaryn

    Soaryn

    Joined:
    Apr 17, 2015
    Posts:
    328
    To do a 2D array really just allocating an 1D array with the "area" of the 2D Array. So instead of having array[x][y] you'd have something like array[x+y*x] or something similar. You'd encode all of it into 1 dimension. It is non-ideal, but it is how most architectures work.

    You unfortunately, can not pass a NativeArray<NativeArray<int>> nor a NativeArray2D<int>; though you could probably create one as a helper using the NativeContainer structures as a guide.
     
    jjbish and whiskers434 like this.
  3. whiskers434

    whiskers434

    Joined:
    Sep 23, 2014
    Posts:
    28
    thank you, I have a workable solution now, its not perfect but it will do

    I am adding all my MoreValues (y's*) to a NativeList and storing the start_index and length in the JobValues struct, then in the job it loops through just the part of the list that is for that index

    Updated sample parallel job
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Collections;
    4. using Unity.Jobs;
    5. using UnityEngine;
    6.  
    7. public class TestJobScript : MonoBehaviour
    8. {
    9.     [System.Serializable]
    10.     struct JobValues
    11.     {
    12.         public int value;
    13.         public int other_value;
    14.         public int more_values_array_start_index;
    15.         public int more_values_array_length;
    16.     }
    17.  
    18.     [System.Serializable]
    19.     struct MoreValues
    20.     {
    21.         public int value;
    22.         public int other_value;
    23.  
    24.         public MoreValues(int value, int other_value)
    25.         {
    26.             this.value = value;
    27.             this.other_value = other_value;
    28.         }
    29.     }
    30.  
    31.     [System.Serializable]
    32.     struct JobResult
    33.     {
    34.         public int result;
    35.         public int other_result;
    36.  
    37.         public JobResult(int result, int other_result)
    38.         {
    39.             this.result = result;
    40.             this.other_result = other_result;
    41.         }
    42.     }
    43.  
    44.     SampleParallelJob sample_job;
    45.     JobHandle job_handle;
    46.     NativeArray<JobValues> job_values;
    47.     NativeList<MoreValues> more_values;
    48.     NativeMultiHashMap<int, JobResult> job_results;
    49.  
    50.     void SampleJob()
    51.     {
    52.         //set up
    53.         job_values = new NativeArray<JobValues>(10, Allocator.TempJob);
    54.         job_results = new NativeMultiHashMap<int, JobResult>(10 * 10, Allocator.TempJob);
    55.         more_values = new NativeList<MoreValues>(Allocator.TempJob);
    56.  
    57.         //get the data
    58.         for (int i = 0; i < 10; i++)
    59.         {
    60.             var values = new JobValues();
    61.             values.value = 1;
    62.             values.other_value = 10;
    63.             values.more_values_array_start_index = i * 10;
    64.             values.more_values_array_length = 10;
    65.  
    66.             for (int j = 0; j < 10; j++)
    67.             {
    68.                 more_values.Add(new MoreValues(1,2));
    69.             }
    70.  
    71.             job_values[i] = values;
    72.         }
    73.  
    74.         //create the job
    75.         sample_job = new SampleParallelJob();
    76.         sample_job.job_values = job_values;
    77.         sample_job.more_values = more_values;
    78.         sample_job.job_results = job_results.ToConcurrent();
    79.  
    80.         //start job
    81.         job_handle = sample_job.Schedule(job_values.Length, 1);
    82.  
    83.         //job complete
    84.         job_handle.Complete();
    85.  
    86.         //handle results
    87.         var results = job_results.GetValueArray(Allocator.Temp);
    88.         for (int i = 0; i < results.Length; i++)
    89.         {
    90.             var temp = results[i].result;
    91.             //process results etc...
    92.         }
    93.  
    94.         //clean up
    95.         results.Dispose();
    96.         job_values.Dispose();
    97.         more_values.Dispose();
    98.         job_results.Dispose();
    99.     }
    100.  
    101.     struct SampleParallelJob : IJobParallelFor
    102.     {
    103.         [ReadOnly]
    104.         public NativeArray<JobValues> job_values;
    105.  
    106.         [ReadOnly]
    107.         public NativeList<MoreValues> more_values;
    108.  
    109.         [WriteOnly]
    110.         public NativeMultiHashMap<int, JobResult>.Concurrent job_results;
    111.  
    112.         public void Execute(int index)
    113.         {
    114.             var job_value = job_values[index];
    115.  
    116.             for (int i = job_value.more_values_array_start_index; i < job_value.more_values_array_start_index + job_value.more_values_array_length; i++)
    117.             {
    118.                 var result = more_values[i].other_value;
    119.                 var other_result = more_values[i].value;
    120.                 job_results.Add(index, new JobResult(result, other_result));
    121.             }
    122.         }
    123.     }
    124. }
    125.