Единственно что - это у тебя еще относительно редко происходили аллокации, т.е. была какая-то тяжелая бизнес-логика?
Это компилятор шейдеров с кучей мап внутри, каждая нода это мелкая аллокация.
Фиксированные буфера показали себя плохо в сценарии, когда бывают чудовищные всплески трафика
Замеры производительности не помню, у меня для системы тасков сделана lock-free очередь на single-linked-list, где внутри небольшой массив на 128 байт. По производительности и само-масштабированию внезапно оказался быстрее других вариантов. Но проверялся определенный сценарий, поэтому для других задач может не подойти.
Сейчас ЦП очень разные, на новых есть 2 ветки предсказания ветвлений, префетч по указателям в структурах и тд, тогда как на более старых все попроще и кэши поменьше и медленее. Еще добавляются E, LP ядра с разными частотами и разными кэшами. Без замеров на всем этом зоопарке я бы предпочел хранить линейно.
Для серверов может и достаточно, но для клиентского кода есть 2 паузы: быстрая типа mm_pause, когда частота ЦП не меняется, и более медленная через таймеры или WFE инструкцию на ARM, тогда ЦП может понизить частоту, меньше греться и не визжать вентиляторами.
Второй тип паузы нужен, когда поток постоянно обрабатывает задачи, но в какой-то момент появляется пауза до 1мс, тогда как переключение потоков или минимальный Sleep(1) на винде заниет 1/64с (около 15мс).
drain_stack
Тут все упирается в выделение памяти для ноды, обычно мелкие аллокации попадают в зарезервированную память в каждом потоке, но рано или поздно они дернут ядро с глоабльным мьютексом. Я сталкивался с тем, что из-за аллокаций алгоритм без синхронизаций вообще не масштабировался более 4 потоков.
Я делал похожие структуры через фиксированный буфер и атомарный счетчик размера, буфер переключается также свопом указателей.
Создавать вторую графическую очередь ради одного барьера это огромный оверхэд. Это софтварные очереди и внутри они отправлют все на один планировщик, так что копирование замедляет рендеринг. Если и создавать очередь то только async transfer (без graphics|compute флагов), вот она реально работает параллельно, но на мобилках таких нет.
Понятно что вызов vkQueueSubmit медленный, но оптимизируется это батчингом всех командных буферов в один сабмит, а не добавлением очередей.
В OpenGL на ПК на случайную аллокацию уходит 10-20мс, что потеря одного кадра. На Vulkan с прямым доступом к железу время увеличивается до 100мс в худшем случае. Причем эта проблема у меня возникла с VMA когда все временные ресурсы удалялись и вся страница памяти на 256Мб освобождалась, а на следующем кадре заново.
Ни один открытый движок не выдерживает нагрузку, которую легко тянут закрытые ААА движки, особенно если оптимизированны под определенную игру. По этой причине есть небольшой спрос на подобные разработки.
Но и риск просто перехода на другой движок большой, не мало компаний закрылись после этого.
В Doom 2016 в UI каждый квадрат отдельным дроуколом рисовали и все равно это наиболее оптимизированый рендер того времени) Сам по себе draw call почти бесплатный.
Скорее пересоздание свопчейна, это происходит при изменении размера окна, там не нужно пересоздавать все ресурсы. В Vulkan есть device lost ошибка, когда что-то пошло не так (упал драйвер), но это если очень повезло, часто все падает.
С видеокартами тоже весело. У меня RTX 2080 работала бесшумного много лет, а потом на играх стал включаться пылесос. Оказалось новый драйвер повысил частоты выше тех, что были в спецификации, пришлось принудительно занижать до базовых 1.5ГГц.
Писать код, который не поймет ИИ. У меня например куча асинхронщины, подписки на события и тд, разобраться в этом можно только с самодельным визуальным отладчиком. А если еще почаще кидать исключения и ловить их на глубине в 10-20 вызовов, то вообще никто не разберется, что там происходит.
Стоит с телефона в дефолтном браузере поискать кухни, так сразу раздается звонок с предложениями. А тут БПЛА от обычного пользователя все никак не могут отличить.
Я находил что у двух производителей есть проблема, когда видеокарта фиксируется на 210МГц и все тормозит, мне хоть повезло и само восстановилось через неделю. Проблема с WiFi вообще массовая, даже дешевый USB адаптер лучше. Еще сильно греется при подключении к USB-C прямо под рукой.
Двухканальная DDR5-8000 это всего 128Гб/с, на 52 ядра это 2.5ГБ/с. Если кто-то сможет распределить задачи на столько ядер.
Кстати, текстуры в играх используются не процессором, они перегоняются с диска на ГПУ через ЦП, а объемы данных такие, что кэш никак не поможет. Если скорость PCI-E около 64ГБ/с, то половина пропускной способности памяти будет уходить на подгрузку открытых миров.
Сейчас не так важно что за SIMD 128-512 поддерживается, так как в железе может быть 4х 128битных пайплайна, то есть 4 инструкции выполняются параллельно. Такое сделано например на Intel E-ядрах и Cortex X4. А на AMD Zen4 был SIMD256 dual issue для эмуляции SIMD512 пока они не сделали полноценные 512 бит на Zen5.
У ЦП reorder buffer 300+ микроинструкций, задержка на чтение RAM около 60нс, на 5ГГц это 300 тактов. Так что в идеальном случае память прочитается даже без кэшей.
В некоторых случаях кэши даже вредны, например memcpy при копировании более 2Мб включает некэшируемое копирование, иначе на заполнение кэшей тратится в 3 раза больше времени.
Для корректности теста автовекторизацию лучше выключить настройками компилятора. А еще неплохо бы посчитать флопсы и Гб/с.
Насчет кэш промахов при случайном доступе нужно считать Гб/с и сравнивать с аналогичным memcpy, тогда будет видно сколько реально идет в RAM, а сколько в кэши. Ничего не мешает ЦП читать массив индексов наперед и префетчить, потери идут только из-за прыгания по кэш линиям из-за чего железо не успевает подгружать данные, а была бы память побыстрее, то и потерь не было бы.
Это компилятор шейдеров с кучей мап внутри, каждая нода это мелкая аллокация.
Замеры производительности не помню, у меня для системы тасков сделана lock-free очередь на single-linked-list, где внутри небольшой массив на 128 байт. По производительности и само-масштабированию внезапно оказался быстрее других вариантов. Но проверялся определенный сценарий, поэтому для других задач может не подойти.
Сейчас ЦП очень разные, на новых есть 2 ветки предсказания ветвлений, префетч по указателям в структурах и тд, тогда как на более старых все попроще и кэши поменьше и медленее. Еще добавляются E, LP ядра с разными частотами и разными кэшами. Без замеров на всем этом зоопарке я бы предпочел хранить линейно.
Для серверов может и достаточно, но для клиентского кода есть 2 паузы: быстрая типа mm_pause, когда частота ЦП не меняется, и более медленная через таймеры или WFE инструкцию на ARM, тогда ЦП может понизить частоту, меньше греться и не визжать вентиляторами.
Второй тип паузы нужен, когда поток постоянно обрабатывает задачи, но в какой-то момент появляется пауза до 1мс, тогда как переключение потоков или минимальный Sleep(1) на винде заниет 1/64с (около 15мс).
Тут все упирается в выделение памяти для ноды, обычно мелкие аллокации попадают в зарезервированную память в каждом потоке, но рано или поздно они дернут ядро с глоабльным мьютексом. Я сталкивался с тем, что из-за аллокаций алгоритм без синхронизаций вообще не масштабировался более 4 потоков.
Я делал похожие структуры через фиксированный буфер и атомарный счетчик размера, буфер переключается также свопом указателей.
Создавать вторую графическую очередь ради одного барьера это огромный оверхэд. Это софтварные очереди и внутри они отправлют все на один планировщик, так что копирование замедляет рендеринг. Если и создавать очередь то только async transfer (без graphics|compute флагов), вот она реально работает параллельно, но на мобилках таких нет.
Понятно что вызов vkQueueSubmit медленный, но оптимизируется это батчингом всех командных буферов в один сабмит, а не добавлением очередей.
В OpenGL на ПК на случайную аллокацию уходит 10-20мс, что потеря одного кадра. На Vulkan с прямым доступом к железу время увеличивается до 100мс в худшем случае. Причем эта проблема у меня возникла с VMA когда все временные ресурсы удалялись и вся страница памяти на 256Мб освобождалась, а на следующем кадре заново.
Ни один открытый движок не выдерживает нагрузку, которую легко тянут закрытые ААА движки, особенно если оптимизированны под определенную игру. По этой причине есть небольшой спрос на подобные разработки.
Но и риск просто перехода на другой движок большой, не мало компаний закрылись после этого.
В Horizon Zero Dawn например 4К draw call и все отлично работает.
draw call'ы дешевые, а вот смена констант/состояний между ними дорогие, так как не дает возможности их эффективно параллелить.
В Doom 2016 в UI каждый квадрат отдельным дроуколом рисовали и все равно это наиболее оптимизированый рендер того времени) Сам по себе draw call почти бесплатный.
Скорее пересоздание свопчейна, это происходит при изменении размера окна, там не нужно пересоздавать все ресурсы. В Vulkan есть device lost ошибка, когда что-то пошло не так (упал драйвер), но это если очень повезло, часто все падает.
С видеокартами тоже весело. У меня RTX 2080 работала бесшумного много лет, а потом на играх стал включаться пылесос. Оказалось новый драйвер повысил частоты выше тех, что были в спецификации, пришлось принудительно занижать до базовых 1.5ГГц.
Только VR теперь без XXX не работает, даже PICO не хочет обновляться, а платежи еще до блокировок не принимали.
Писать код, который не поймет ИИ. У меня например куча асинхронщины, подписки на события и тд, разобраться в этом можно только с самодельным визуальным отладчиком. А если еще почаще кидать исключения и ловить их на глубине в 10-20 вызовов, то вообще никто не разберется, что там происходит.
Стоит с телефона в дефолтном браузере поискать кухни, так сразу раздается звонок с предложениями. А тут БПЛА от обычного пользователя все никак не могут отличить.
Я находил что у двух производителей есть проблема, когда видеокарта фиксируется на 210МГц и все тормозит, мне хоть повезло и само восстановилось через неделю. Проблема с WiFi вообще массовая, даже дешевый USB адаптер лучше. Еще сильно греется при подключении к USB-C прямо под рукой.
У меня тоже самое на Asus за 150к. Хотя с ноутами мне вообще не везет.
Двухканальная DDR5-8000 это всего 128Гб/с, на 52 ядра это 2.5ГБ/с. Если кто-то сможет распределить задачи на столько ядер.
Кстати, текстуры в играх используются не процессором, они перегоняются с диска на ГПУ через ЦП, а объемы данных такие, что кэш никак не поможет. Если скорость PCI-E около 64ГБ/с, то половина пропускной способности памяти будет уходить на подгрузку открытых миров.
Все решается проще через flat квалификатор. Была бы там поддержка интов, без него вообще бы шейдер не скомпилировался.
Под AVX тоже есть расширения, например AVX-VNNI для Intel, который повторяет AVX512-VNNI.
Я все же про то, что решает распараллеливание инструкций, а не длина SIMD.
Сейчас не так важно что за SIMD 128-512 поддерживается, так как в железе может быть 4х 128битных пайплайна, то есть 4 инструкции выполняются параллельно. Такое сделано например на Intel E-ядрах и Cortex X4. А на AMD Zen4 был SIMD256 dual issue для эмуляции SIMD512 пока они не сделали полноценные 512 бит на Zen5.
У ЦП reorder buffer 300+ микроинструкций, задержка на чтение RAM около 60нс, на 5ГГц это 300 тактов. Так что в идеальном случае память прочитается даже без кэшей.
В некоторых случаях кэши даже вредны, например memcpy при копировании более 2Мб включает некэшируемое копирование, иначе на заполнение кэшей тратится в 3 раза больше времени.
Для корректности теста автовекторизацию лучше выключить настройками компилятора. А еще неплохо бы посчитать флопсы и Гб/с.
Насчет кэш промахов при случайном доступе нужно считать Гб/с и сравнивать с аналогичным memcpy, тогда будет видно сколько реально идет в RAM, а сколько в кэши. Ничего не мешает ЦП читать массив индексов наперед и префетчить, потери идут только из-за прыгания по кэш линиям из-за чего железо не успевает подгружать данные, а была бы память побыстрее, то и потерь не было бы.