2016-07-12 2 views
4

Nicol Bolas:Многопоточность рендеринг против командных бассейнов

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

функции (5.1 Command Пулы) (курсив мой):

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

Разве это не убивает всю цель пулов команд, когда речь заходит о параллельной записи? Если вы собираетесь записывать параллельно, тогда вам лучше не иметь отдельный пул для каждого потока, не так ли?

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

Я лично не знаю, почему вы не просто предварительно записали все. Так почему же нужно так строить командные буферы параллельно? И вам действительно нужно было бы использовать один пул на поток?

+0

Полюбите то, как вы просто положили Николь Боласа в первую очередь - он, кажется, способен ответить на каждый вопрос о Вулкане, который я могу придумать. Необходимость использования отдельного пула в потоке не убивает цели командных буферов - в какой ситуации пул, который командный буфер выделяет, ограничивает набор команд, которые вы можете поместить в буфер? –

+0

@AndrewWilliamson, очень плохая опечатка, я имел в виду цель команды ** пулы ** _. – Shahbaz

+0

Каждый поток может по-прежнему создавать и уничтожать командные буферы очень часто. Для этого сценария есть пулы. –

ответ

6

Если вы собираетесь записывать параллельно, то вам лучше не иметь отдельный пул для каждой темы, не так ли?

Я не вижу, как наличие отдельного пула за нить «убивает всю цель пулов команд, когда дело доходит до записи параллельно». В самом деле, это немного помогает, так как каждый поток может управлять собственным пулом команд по своему усмотрению.

Рассмотрите структурную разницу между, скажем, пулом дескрипторов и пулом команд. С пулом дескрипторов вы в основном говорите именно то, что вы выделите из него. VkDescriptorPoolCreateInfo предоставляет подробную информацию, которая позволяет реализациям выделять вверх, точно, сколько памяти вы будете использовать для каждого пула. И вы не можете выделить больше, чем это из пула дескрипторов.

В отличие от этого, VkCommandPoolCreateInfo содержит ... ничего. О, вы говорите, если буферы команд могут быть первичными или вторичными. Вы говорите, будут ли буферы команд часто перезагружаться или постоянно. И еще пара вещей. Но кроме этого вы ничего не говорите о содержимом буферов команд. Вы даже не даете ему информации о том, сколько буферов вы выделите.

Пустыни дескрипторов предназначены для фиксации: выделяются по мере необходимости, но до количества, установленного во время строительства. Командные буферы призваны быть очень динамичными: выделены из необходимых для ваших конкретных случаев использования.

Думайте об этом, так как каждый бассейн имеет свой собственный malloc/free. Поскольку пользователь вынужден синхронизировать доступ к пулам и их буферам, это означает, что каждая функция vkCmd* не требуется для этого при распределении памяти. Это ускоряет создание команд. Это помогает резьба.Когда поток решает сбросить свой пул команд, ему не нужно блокировать какие-либо мьютексы или любые другие подобные вещи для этого.

Нет ничего принципиально неправильного с наличием одного пула команд в потоке. Действительно, наличие двух потоков (двойной буферизации) имеет еще больший смысл.

Я лично не знаю, почему вы не просто предварительно записали все.

Потому что вы не делаете статическую техническую демонстрацию.

Я предполагаю, что это происходит из-за недостатка опыта, но я предполагал, что параллельная запись будет выглядеть как «потоковые вторичные буферы команд 2-N потоков, поток 1 вызывает их все в одном основном командном буфере», в котором В каждом потоке имеется только один командный буфер. Вот почему я сказал, что это убивает цель пулов команд, потому что вы делаете только одно выделение на пул.

Это, безусловно, жизнеспособная форма ведения буферов команд параллельно. Но есть две вещи, которые вы пропустили.

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

И даже если это не так, вы забываете о буферизации. Когда придет время построить CB для следующего кадра, вы не можете просто перезаписать существующие. В конце концов, они, вероятно, все еще в очереди делают работу. Поэтому для каждой нити потребуется не менее два CB; тот, который в настоящее время выполняется, и тот, который в настоящее время строится.

И даже если бы это было не так, пулы команд выделяют всю память, связанную с ЦБ. Есть причина, по которой я их сопоставлял с malloc/free. Даже если вы используете только один CB с определенным пулом, тот факт, что выделение этого ЦБ (что может произойти из-за любой функции vkCmd*), никогда не синхронизируется с другим потоком - это хорошо.

Нет, это никоим образом не препятствует использованию нескольких потоков для создания CB.

+0

Typo в моем посте: _ вся цель команды ** пулы ** _, извините за это. – Shahbaz

+0

Я предполагаю, что это происходит из-за отсутствия опыта, но я подумал, что параллельная запись будет выглядеть как «потоки 2-N потоков вторичных команд», поток 1 вызывает их все в одном основном командном буфере », и в этом случае есть только один командный буфер на поток. Вот почему я сказал, что это убивает цель пулов команд, потому что вы делаете только одно выделение на пул. – Shahbaz

+0

@Shahbaz: Ваша опечатка не повлияла на мой ответ. –

1

Если вы собираетесь записывать параллельно, то вам лучше не иметь отдельный пул для каждой нити, не так ли?

Это точно. Это то, что подразумевается в вашей спецификации.

Я бы это понял, если бы вы предварительно записывали командные буферы, выделенные из одного пула (в одном потоке), а затем выполняли их параллельно.

Vulkan делает лучше. Вы можете предварительно записать командные буферы (выделенные из пулов потоков) параллельно и, затем выполнить их параллельно (если ваша рабочая нагрузка способна к этому).

Я лично не знаю, почему вы не просто предварительно записали все. Так почему же нужно так строить командные буферы параллельно?

Потому что это сложно (особенно по мере того, как ваше приложение растет по сложности). В какой-то момент даже непротиворечивый (когда вы поворачиваете CmB, чтобы быть предварительно записываемым - например, заполняя его пустыми привязками заполнителей, из которых 80% из них не будут использоваться).
Это не обязательно «необходимо», Vulkan просто позволяет вам выбрать то, что вы считаете лучшим для своего приложения (или его части).

+1

«* Это не обязательно необходимо, Vulkan просто дает вам дополнительную возможность. *« Еще лучше, Vulkan позволяет * выбрать *. Вы можете предварительно записать некоторые вещи (фильтры после обработки, представление изображений и т. Д.), А также динамическое заполнение других. –

Смежные вопросы