Что такое на самом деле семья Queue в Vulkan? - PullRequest
3 голосов
/ 21 марта 2019

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

Сейчас я анализирую QueuFamilies, для которых у меня есть следующий код:

vector<vk::QueueFamilyProperties> queue_families = device.getQueueFamilyProperties();
for(auto &q_family : queue_families)
{
    cout << "Queue number: "  + to_string(q_family.queueCount) << endl;
    cout << "Queue flags: " + to_string(q_family.queueFlags) << endl;
}

Это дает такой вывод:

Queue number: 16
Queue flags: {Graphics | Compute | Transfer | SparseBinding}
Queue number: 1
Queue flags: {Transfer}
Queue number: 8
Queue flags: {Compute}

Итак, наивно я понимаю это так:

Существует 3 семейства очередей, одно семейство очередей имеет 16 очередей, каждая из которых способна выполнять операции графики, вычисления, передачи и разреженного связывания (понятия не имею, что представляют собой последние 2)

Другой имеет 1 очередь, способную только к передаче (что бы это ни было)

И последняя имеет 8 очередей, способных к вычислительным операциям.

Что такое каждая семья очереди? Я понимаю, что именно здесь мы посылаем команды выполнения, такие как буферы рисования и обмена, но это довольно широкое объяснение, я хотел бы получить более компетентный ответ с более подробной информацией.

Какие 2 дополнительных флага? Трансфер и SparseBidning?

И наконец, почему у нас есть / нужно несколько командных очередей?

Ответы [ 2 ]

8 голосов
/ 21 марта 2019

Чтобы понять семейства очередей, сначала нужно понять очереди.

Очередь - это то, что вы отправляете в буферы команд, а буферы команд, отправляемые в очередь, выполняются в порядке [* 1] относительно друг друга. Буферы команд, отправленные в разные очереди, неупорядочены относительно друг друга, если вы явно не синхронизируете их с VkSemaphore. Вы можете отправлять работу в очередь только из одного потока, но разные потоки могут одновременно отправлять работу в разные очереди.

Каждая очередь может выполнять только определенные виды операций. Графические очереди могут запускать графические конвейеры, запускаемые командами vkCmdDraw*. Очереди вычислений могут запускать конвейеры вычислений, запущенные vkCmdDispatch*. Очереди передачи могут выполнять операции передачи (копирования) с vkCmdCopy*. Очереди разреженной привязки могут изменить привязку разреженных ресурсов к памяти с помощью vkQueueBindSparse (обратите внимание, что это операция, отправляемая непосредственно в очередь, а не команда в буфере команд). Некоторые очереди могут выполнять несколько видов операций. В спецификации каждая команда, которая может быть отправлена ​​в очередь, имеет таблицу «Свойства команды», в которой перечислены типы очередей, которые могут выполнять команду.

Семейство очередей просто описывает набор очередей с одинаковыми свойствами. Итак, в вашем примере устройство поддерживает три вида очередей:

  • Один вид может выполнять операции графики, вычисления, передачи и разреженного связывания, и вы можете создать до 16 очередей этого типа.

  • Другой вид может выполнять только операции передачи, и вы можете создать только одну очередь такого рода. Обычно это для асинхронной передачи данных DMA между памятью хоста и устройства на дискретных графических процессорах, поэтому передачи могут выполняться одновременно с независимыми графическими / вычислительными операциями.

  • Наконец, вы можете создать до 8 очередей, которые могут выполнять только вычислительные операции.

Некоторые очереди могут соответствовать только отдельным очередям в планировщике на стороне хоста, другие очереди могут соответствовать фактическим независимым очередям в аппаратном обеспечении. Например, многие графические процессоры имеют только одну аппаратную графическую очередь, поэтому даже если вы создадите две VkQueues из семейства очереди с графической поддержкой, буферы команд, отправленные в эти очереди, будут проходить через планировщик буфера команд драйвера ядра независимо, но будут выполняться в некоторых последовательных Заказ на ГПУ. Но некоторые графические процессоры имеют несколько аппаратных очередей только для вычислений, поэтому две VkQue для семейства очередей только для вычислений могут фактически проходить независимо и одновременно по всему графическому процессору. Вулкан этого не разоблачает.

Итог, решите, сколько очередей вы можете использовать с пользой, исходя из того, сколько у вас параллелизма. Для многих приложений единственная «универсальная» очередь - это все, что им нужно. Более продвинутые могут иметь одну графическую + вычислительную очередь, отдельную очередь только для вычислений для асинхронной вычислительной работы и очередь передачи для асинхронного DMA. Затем сопоставьте то, что вы хотите, с тем, что доступно; вам может потребоваться выполнить собственное мультиплексирование, например, на устройстве, которое не имеет семейства очередей только для вычислений, вы можете вместо этого создать несколько графических + вычислительных очередей или сериализовать асинхронные вычислительные задания в единую графическую + вычислительную очередь самостоятельно.

[* 1] Немного упрощение. Они начинают по порядку, но после этого им разрешается действовать независимо и завершаться не в порядке. Независимый прогресс различных очередей не гарантируется. Я оставлю это на этот вопрос.

5 голосов
/ 21 марта 2019

Очередь - это вещь, которая принимает командные буферы, содержащие операции определенного типа (заданные флагами семейства).Команды, переданные в очередь, имеют порядок отправки, поэтому они подлежат синхронизации с помощью конвейерных барьеров, зависимостей подпрохода и событий (в то время как между очередями следует использовать семафор или луч).

Есть одна хитрость: COMPUTE и GRAPHICS всегда могут неявно принять TRANSFER рабочую нагрузку (даже если QueueFamilyProperties не перечислять ее).

Передача для команд копирования и Blit.Разреженный это что-то вроде пейджинга;он позволяет привязывать несколько дескрипторов памяти к одному изображению, а также позволяет позже повторно привязывать другую память.

В спецификации, приведенной ниже данной команде vkCmd*, всегда указывается, какие из них являются «поддерживаемыми типами очереди».".

Семейство очередей - это группа очередей, которые имеют особое отношение к себе.Некоторые вещи ограничены одним семейством очередей, например, изображения (они должны быть переданы между семействами очередей) или пул команд (создает буферы команд только для использования данным семейством очередей и никаким другим).Теоретически на каком-то экзотическом устройстве может быть больше семей с одинаковыми флагами.

Это почти все, что гарантирует спецификация Vulkan.См. Проблему с этим в KhronosGroup / Vulkan-Docs # 569


Приведены некоторые специфичные для поставщика материалы, например:

Графические процессоры имеют асинхронный графический процессор (ы), вычисленияEngine (s), и Copy \ DMA Engine (s).Графика и вычисления, разумеется, будут оспаривать одни и те же вычислительные единицы графического процессора.

У них обычно есть только один графический интерфейс.Это является узким местом для графических операций, поэтому нет смысла использовать более одной графической очереди.

Существует два режима работы для вычислений: синхронное вычисление (отображается как семейство GRAPHICS|COMPUTE) и асинхронное вычисление(выставлено как COMPUTE -только семья).Первый - это безопасный выбор.Второй может дать вам около 10% производительности, но он более сложный и требует больше усилий.В статье AMD предлагается всегда делать первое в качестве базового уровня.

Теоретически может быть столько вычислительных очередей, сколько вычислительных блоков на GPU.Но AMD утверждает, что нет никакой выгоды для более чем двух Async Compute Queues и выставляет такое количество.NVIDIA, кажется, идет с полным номером.

Двигатели Copy \ DMA (представленные только как семейство TRANSFER) в основном предназначены для передачи CPU-GPU.Обычно они не достигают полной пропускной способности для копии внутри GPU.Таким образом, если нет какой-то магии драйвера, семейство Async Transfer следует использовать для передачи CPU⇄GPU (чтобы пожинать свойство Async, чтобы иметь возможность делать графику рядом с ним беспрепятственно).Для копий внутри GPU в большинстве случаев лучше использовать семейство GRAPHICS|TRANSFER.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...