Думаю над тем, как лучше всего распараллелить игру. Раньше я параллелил только отдельные задачи, а остальное было линейным.
Думаю запускать потоки. Сначала хотел запускать 1 поток для рендера и ещё несколько потоков, которые бы делали одну и ту же работу для разных частей одних данных, после чего в главном потоке собрать результат их деятельности. Както так:
void redraw(){
}
void update(float dt, Data* ы, int count){ printf("дороу"); }
Но это будя очень сложно. Допустим, я симулирую физику. Допустим, что первый поток выполняет физику для первой четверти объектов, второй поток для второй четверти и тд. Но чтобы обработать физику, нужно знать инфу обо всех объектах, чтобы проверять пересечения (проверка каждого с каждым). Тогда получается нужно нехило так синхронизировать общие данные, сомнительная выгода. Можно делить объекты на потенциально столкнувшиеся независимые группы и делить нагрузку на потоки по этим группам. Но бяда, подобный препроцессинг надо делать каждый кадр, скорее всего, с использованием недружелюбных к кэшу и вечно теребящих динамическую память std::set'ов и прочих прочих делов. Сомнительный выигрыш. К тому же, если вдруг все объекты в мире столкнутся в единую кашу, эту кашу придётся разгребать одному потоку, а это тяжелейший случай из возможных. Имея притом тяжёленький препроцессинг, который ничем не помох)
Кроме того, хочу прибабасать к игре луа скрипты, а это дело не является потокобезопасным. А копировать одни и те же скрипты между потоками запрещает религия. Поясню: есть, грубо говоря, класс "пушка"; я создаю 400 экземпляров этой пушки, но к классу пушки присобачен луа скрипт (зачем грузить один и тот же скрипт для каждого инстанса пушки, если можно грузить скрипты отдельно, а объектам подсовывать хендл нужного скрипта). Но я не могу разделить по 100 пушек на каждый поток и обращаться из нескольких потоков по хендлам скрипта из пушек к скрипту, на который они все ссылаются. Получается, нужно хранить этот скрипт для каждого из потоков, то есть, по 4 одинаковых скрипта подряд? Бред.
Поэтому решил вместо распараллеливания данных распараллелить задачи. Поток для рендеринга, поток для ИИ, поток для физики и т.д. И тут же вопрос. Допустим, что рендеринг и физика намного легковеснее, чем скажем, ИИ (просто допустим). Тогда я хочу в потоке для ИИ для особо тяжкой внутренней задачи сделать дополнительный параллельный цикл Concurrency::parallel_for(бла бла бла), чтобы частично подгрузить и другие ядра, чтобы не было ситуации, что потоки для физики и рендеринга давно закончили обработку кадра, а ИИ даже половину работы не выполнил. Вопрос, компухтер не сойдёт с ума от такого распараллеливания внутри распараллеливания?
Если допустить, что у меня одно ядро в процессоре и я вынесу логику в один поток, а рендеринг в другой, производительность вырастет или упадёт? Допустим, что тяжёлой синхронизации не понадобится.
Далее, как лучше пускать потоки? 1) Запускать в начале игры и они, грубо говоря, фурычат на максимуме каждый своё с разной скоростью? То есть, допустим, поток для рендеринга успел перерисовать ажно 5 раз на основе предсказаний, пока поток для логики наярил только 1 круг. 2) (сейчас я хочу сделать именно так) Пускать потоки каждую итерацию главного игрового цикла и ждать, пока они все не завершатся. (тобишь время работы самого медлительного из этих потоков будет временем формирования кадра, остальные потоки, когда закончат обрабатывать свои задачи в текущем кадре, отдыхают и ждут самого неторопливого) Не будет ли сама процедура запуска потоков по 60 раз в секунду уничтожать всю выгоду от распараллеливания? Может быть, можно запустить эти потоки вначале, а внутри игрового цикла просто давать им сигнал продолжить работу, тогда как они сами будут нас уведомлять о том, что очередная итерация работы окончена и автоматически становиться на паузу (с помощью какихнибудь условных переменных чтоли) 3)ещё как-то?
В отдельные потоки можно вынести асинхронные задачи, к примеру обновление звука (если звук воспроизводится потоково), то есть то, что не требует синхронизации, ибо синхронизация требует времени и ее неправильная организация может только навредить. Если много геометрии и вообще всего того что будет рисоваться, то самое тормознутое место это именно сам рендер. Главный цикл надо оптимизировать: сначала как можно больше рендера (можно совместно с просчетами, чтобы синхронизировать работу gpu и cpu), а после уже основные просчеты (физика, ИИ, просчеты видимости и прочее). Пока gpu будет рисовать cpu будет считать, а потом кто-то кого-то ждет)) Думаю после оптимизации главного цикла будет намного легче понять что нужно куда выносить и надо ли вообще это делать.
А вообще что больше всего тормозит? Метрика есть?
Метрика тормозов из нашего движка SkyXEngine:
Кстати ИИ необязательно каждый кадр считать. Если вспомнить игры серии Сталкер, то там НПС порой притормаживают, из этого можно сделать вывод что ИИ считается не каждый кадр (может быть чем ближе к игроку тем чаще, но хз). Мой блог - ссылка Мои проекты: SkyXEngine - графический 3D движок с real-time рендером s4g - скриптовый язык программирования
Сообщение отредактировал Byurrer - Вторник, 07 Ноября 2017, 08:51
моя 2д игра и на слабых ПК без особых оптимизаций пойдёт
может быть тогда лучше игру доделывать)) По теме: нужна метрика чтобы понять где больше всего времени требуется, а затем уже думать что делать с тормозом, потому что одно дело вынести физику, а другое дело разгрузить ИИ (к примеру через кадр глобальное обновление, а НПС обновлять в зависимости от дистанции до игрока). Мой блог - ссылка Мои проекты: SkyXEngine - графический 3D движок с real-time рендером s4g - скриптовый язык программирования
Если интересно копаться в исходниках, то глянь (наш движок SkyXEngine) https://dev.ds-servers.com/sip/engine/tree/dev/source/core все что связанно с task и также в sxcore.h загляни, накидали, тестанули, но внедрять не стали, не до этого пока)) Мой блог - ссылка Мои проекты: SkyXEngine - графический 3D движок с real-time рендером s4g - скриптовый язык программирования
Сообщение отредактировал Byurrer - Вторник, 07 Ноября 2017, 14:15
Byurrer, спасибо) Так прямо сходу не разберусь, но какие-то вещи вроде выглядят более-менее понятными. Но пока что трогать это дело сильно не буду, иначе это надолго) https://vk.com/beezoya