Найти тему
Виталий Власов

Native Container in Unity DOTs

Добрый день, сегодня я расскажу про Native Container.
Недостатком процесса копирования данных
системы безопасности (Job system) является то, что он также изолирует результаты работы в каждой копии. Чтобы преодолеть это ограничение, вам нужно хранить результаты в виде разделяемой памяти, называемой NativeContainer .

Что такое NativeContainer?

A NativeContainer- это тип управляемого значения, который обеспечивает относительно безопасную оболочку C# для собственной памяти. Содержит указатель на неуправляемое распределение. При использовании с Job system Unity C# a NativeContainer позволяет заданию получать доступ к данным, передаваемым в основной поток, а не работать с копией.

Какие типы NativeContainer доступны?

Unity поставляется с так NativeContainer называемым NativeArray . Вы также можете манипулировать NativeArray с NativeSlice,чтобы получить подмножество NativeArray из определенной позиции до определенной длины.

Примечание . Пакет Entity Component System (ECS) расширяет Unity.Collections пространство имен и включает в себя другие типы NativeContainer:

  • NativeList- изменяемого размера NativeArray.
  • NativeHashMap - ключ и значение пары.
  • NativeMultiHashMap - несколько значений на ключ.
  • NativeQueue- очередь.

NativeContainer и Job System

Система безопасности встроена во все NativeContainer типы. Он отслеживает то, что читает и пишет любому NativeContainer.

Примечание . Все проверки безопасности для NativeContainer типов (такие как проверки за пределами границ, проверки освобождения и проверки состояния гонки) доступны только в редакторе Unity и в режиме воспроизведения .

Частью этой системы безопасности являются DisposeSentinel и AtomicSafetyHandle . В DisposeSentinel протечках детектируют память и дает ошибку , если вы не правильно освободили свою память. Инициирование ошибки утечки памяти происходит спустя много времени после утечки.

Используйте AtomicSafetyHandle для передачи права собственности NativeContainer в коде. Например, если два запланированных задания записывают в одно и то же NativeArray, система безопасности выдает исключение с четким сообщением об ошибке, которое объясняет, почему и как решить проблему. Система безопасности выдает это исключение при планировании неправильной работы(Job).

В этом случае вы можете запланировать работу с зависимостью. Первое задание может быть записано в NativeContainer, и, как только оно закончится, следующее задание может затем безопасно прочитать и записать в то же самое NativeContainer. Ограничения чтения и записи так
же применяются при доступе к данным из основного потока. Система безопасности позволяет нескольким заданиям считывать одни и те же данные параллельно.

По умолчанию, когда задание имеет доступ к NativeContainer, оно имеет доступ как для чтения, так и для записи. Эта конфигурация может снизить производительность. Job System C# не позволяет вам планировать задание, у которого есть доступ на запись, NativeContainer одновременно с другим заданием, которое записывает в него.

Если заданию не нужно писать в NativeContainer, пометьте NativeContaine [ReadOnly]атрибутом, например так:

В приведенном выше примере вы можете выполнить задание одновременно с другими заданиями, которые также имеют доступ только для чтения к первому NativeArray.
В приведенном выше примере вы можете выполнить задание одновременно с другими заданиями, которые также имеют доступ только для чтения к первому NativeArray.

Примечание . Нет защиты от доступа к статическим данным из задания. Доступ к статическим данным обходит все системы безопасности и может привести к сбою Unity. Для получения дополнительной информации см. Советы по работе с системой C # и устранение неполадок .

NativeContainer Allocator

При создании NativeContainer вы должны указать тип выделения памяти, который вам нужен. Тип распределения зависит от продолжительности выполнения задания. Таким образом, вы можете настроить распределение для достижения максимальной производительности в каждой ситуации.

Есть три Allocator типа для NativeContainer выделения и освобождения памяти. Вы должны указать соответствующий при создании вашего NativeContainer.

  • Allocator.Temp имеет самое быстрое размещение. Это для распределений с продолжительностью жизни одного кадра или меньше. Вы не должны передавать NativeContainer Allocator.Temp на работу. Вам также необходимо вызвать Dispose метод, прежде чем вернуться из вызова используемого метода (например, MonoBehaviour.Update или любого другого обратного вызова из собственного в управляемый код).
  • Allocator.TempJob - это медленное распределение Temp, но оно быстрее, чем Persistent. Он предназначен для выделения в течение срока службы четырех кадров и является поточно-ориентированным. Если вы этого не сделаете Dispose в течение четырех кадров, консоль напечатает предупреждение, сгенерированное из собственного кода. Большинство небольших заданий используют этот NativeContainer тип распределения.
  • Allocator.Persistent является самым медленным распределением, но может длиться столько, сколько вам нужно, и при необходимости в течение всего срока службы приложения. Это обертка для прямого вызова malloc . Более длинные работы могут использовать этот NativeContainer тип распределения. Вы не должны использовать Persistent там, где важна производительность.

Например:

NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);
NativeArray<float> result = new NativeArray<float>(1, Allocator.TempJob);

Примечание . Число 1 в приведенном выше примере указывает на размер NativeArray. В этом случае он имеет только один элемент массива (так как в нем хранится только один фрагмент данных result).

В следующей статье будет рассказано про Job System!|
Подписывайтесь на нашу группу:
https://vk.com/unitylibrary

С подпиской рекламы не будет

Подключите Дзен Про за 159 ₽ в месяц