Мои Уведомления
Привет, !
Мой Аккаунт Мои Финансы Мои Подписки Мои Настройки Выход
Руководство API скрипты

Недостаток системы безопасности процесса копирования данных заключается в том, что он также изолирует результаты работы внутри каждой копии. Чтобы преодолеть это ограничение, вам необходимо хранить результаты в общей памяти типа NativeContainer.

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

Типы NativeContainer

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

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

  • NativeList – NativeArray с изменяемым размером.
  • NativeHashMap — пары "ключ-значение".
  • NativeMultiHashMap – несколько значений для каждого ключа.
  • NativeQueue — первый пришел, первый вышел (FIFO).

NativeContainer и система безопасности

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

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

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

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

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

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

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

[ReadOnly] public NativeArray input;

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

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

Распределитель NativeContainer

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

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

  • Allocator.Temp имеет самое быстрое выделение. Используйте его для выделений со сроком жизни один кадр или меньше. Однако вы не можете использовать Temp для передачи выделений NativeContainer заданиям.
  • Allocator.TempJob обеспечивает более медленное выделение, чем Temp, но быстрее, чем Persistent. Используйте его для потокобезопасных распределений в течение четырех кадров. Важно: вы должны удалить этот тип распределения в течение четырех кадров, иначе консоль выведет предупреждение, сгенерированное из собственного кода. В большинстве небольших заданий используется этот тип распределения NativeContainer.
  • Allocator.Persistent — это самый медленный процесс выделения, но он может длиться столько, сколько вам нужно, а при необходимости — на протяжении всего жизненного цикла приложения. Это оболочка для прямого вызова malloc. Более длинные задания могут использовать этот тип распределения NativeContainer. Не используйте Persistent, если важна производительность.

Например:

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

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

Вы можете отблагодарить автора, за перевод документации на русский язык. ₽ Спасибо
Руководство Unity 2021.3