Параллельные работы
Когда вы планируете задание, его метод Execute выполняется один раз. Однако могут возникнуть ситуации, когда вам нужно выполнить одну и ту же операцию на большом количестве объектов. Для этого используйте тип задания ParallelFor, который наследует от IJobParallelFor.
Задание ParallelFor использует данные NativeArray в качестве источника данных. Задания ParallelFor выполняются на нескольких ядрах CPU. На каждом ядре выполняется одно задание, каждое из которых обрабатывает подмножество рабочей нагрузки.
IJobParallelFor ведет себя как IJob, но вместо одного метода Execute он вызывает метод Execute один раз на элемент в источнике данных. В методе Execute также есть индекс параметра целочисленного числа, который можно использовать для доступа и работы с одним элементом источника данных в реализации задания.
Ниже приведен пример определения задания ParallelFor:
struct IncrementByDeltaTimeJob: IJobParallelFor
{
public NativeArray<float> values;
public float deltaTime;
public void Execute (int index)
{
float temp = values[index];
temp += deltaTime;
values[index] = temp;
}
}
Запланировать задание ParallelFor
Планированиеa ParallelFor работу, вы должны указать длину NativeArray источник данных, который вы хотите разделить. Система заданий не знает, какие NativeArray который вы хотите использовать как источник данных, если их в структуре несколько. Длина также сообщает системе заданий, сколько Execute методы ожидать.
В нативном коде Unity планирование заданий ParallelFor более сложно. Когда Unity планирует задание ParallelFor, система заданий разделяет работу на пакета для распределения между ядрами. Каждая пакет содержит подмножество методов Execute. Затем система заданий планирует одно задание в нативной системе заданий Unity на ядро CPU и передает это нативное задание пакетам для завершения.
Когда основное задание завершает свои пакета раньше других, оно кражи оставшиеся пакета из других нативных заданий. Он только крадет половину оставшихся пакетов нативного задания за один раз, чтобы обеспечить кэш locality.
Для оптимизации процесса, вам нужно указать количество пакетов. Количество пакетов контролирует, сколько заданий вы получаете, и насколько мелкозернистое перераспределение работы между потоками. Имея низкое количество пакетов, например, 1, дает вам равномерное распределение работы между потоками. Однако, это приводит к некоторым накладным расходам, поэтому иногда лучше увеличить количество пакетов. Начиная с 1 и увеличивая количество пакетов, пока не будет незначительного повышения производительности является хорошей стратегией.
Ниже приведен пример планирования задания ParallelFor
Код работы:
// Job adding two floating point values together
public struct MyParallelJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<float> a;
[ReadOnly]
public NativeArray<float> b;
public NativeArray<float> result;
public void Execute(int i)
{
result[i] = a[i] + b[i];
}
}
Код основной нити:
NativeArray<float> a = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> b = new NativeArray<float>(2, Allocator.TempJob);
NativeArray<float> result = new NativeArray<float>(2, Allocator.TempJob);
a[0] = 1.1f;
b[0] = 2.2f;
a[1] = 3.3f;
b[1] = 4.4f;
MyParallelJob jobData = new MyParallelJob();
jobData.a = a;
jobData.b = b;
jobData.result = result;
// Schedule the job with one Execute per index in the results array and only 1 item per processing batch
JobHandle handle = jobData.Schedule(result.Length, 1);
// Wait for the job to complete
handle.Complete();
// Free the memory allocated by the arrays
a.Dispose();
b.Dispose();
result.Dispose();
ParallelForTransform вакансии
Задание ParallelForTransform является другим типом задания ParallelFor, специально разработанным для работы с Преобразования. Оно полезно для эффективной работы с операциями Transform из заданий.