Откровенно говоря, общий подход к использованию нескольких ядер просто ошибочен. Разделение ваших подсистем на разные потоки действительно разделит часть работы на несколько ядер, но у нее есть некоторые серьезные проблемы. Во-первых, с ним очень сложно работать. Кто хочет возиться с блокировками, синхронизацией, связью и прочим, когда вместо этого они могут просто писать код для рендеринга или физический код? Во-вторых, подход на самом деле не расширяется. В лучшем случае это позволит вам использовать, возможно, три или четыре ядра, и это если вы действительно знаете, что делаете. В игре только так много подсистем, а из них еще меньше, которые занимают большие куски процессорного времени. Есть пара хороших альтернатив, которые я знаю.
Одним из них является наличие основного потока вместе с рабочим потоком для каждого дополнительного ЦП. Независимо от подсистемы основной поток делегирует изолированные задачи рабочим потокам через своего рода очереди; эти задачи сами могут создавать и другие задачи. Единственной целью рабочих потоков является то, чтобы каждый захватывал задачи из очереди по одному и выполнял их. Тем не менее, наиболее важным является то, что, как только потоку нужен результат задачи, если задача завершена, он может получить результат, а если нет, то может безопасно удалить задачу из очереди и продолжить и выполнить это. Само задание. То есть не все задачи будут планироваться параллельно друг другу. Имея больше задач , чем может выполняться параллельно является хорошимвещь в этом случае; это означает, что он может масштабироваться при добавлении большего количества ядер. Одним из недостатков этого является то, что для разработки достойной очереди и рабочего цикла требуется много усилий, если у вас нет доступа к библиотеке или языковой среде выполнения, которая уже обеспечивает это для вас. Самое сложное - убедиться, что ваши задачи действительно изолированы и надежно защищены от потоков, а также убедиться, что ваши задачи находятся в хорошем положении между крупнозернистым и мелкозернистым.
Другой альтернативой потокам подсистем является распараллеливание каждой подсистемы изолированно. То есть вместо того, чтобы запускать рендеринг и физику в своих собственных потоках, напишите подсистему физики, которая будет использовать все ваши ядра одновременно, напишите подсистему рендеринга, которая будет использовать все ваши ядра одновременно, а затем просто запустите две системы (или с чередованием, в зависимости от других аспектов вашей игровой архитектуры). Например, в подсистеме физики вы можете взять все точечные массы в игре, разделить их между ядрами, а затем заставить все ядра обновлять их одновременно. Каждое ядро может работать с вашими данными в тесных циклах с хорошей локализацией. Этот стиль параллелизма с блокировкой шагов аналогичен тому, что делает GPU. Самое сложное в этом состоит в том, чтобы убедиться, что вы делите свою работу на мелкозернистые куски, чтобы делить ее равномернофактически приводит к одинаковому объему работы на всех процессорах.
Однако иногда из-за политики, существующего кода или других неприятных обстоятельств проще всего дать каждой подсистеме поток. В этом случае лучше избегать создания большего количества потоков ОС, чем ядер, для тяжелых рабочих нагрузок ЦП (если у вас есть среда выполнения с легкими потоками, которые просто сбалансированы между вашими ядрами, это не так уж сложно). Также избегайте чрезмерного общения. Один хороший трюк - попробовать конвейерную работу; каждая основная подсистема может одновременно работать в разных игровых состояниях. Конвейерная конвейерная обработка уменьшает количество коммуникаций, необходимых между вашими подсистемами, так как им не нужен доступ к одним и тем же данным в одно и то же время, и это также может свести на нет часть ущерба, вызванного узкими местами. Например, если ваша физическая подсистема имеет тенденцию занимать много времени и ваша подсистема рендеринга всегда ждет ее, ваша абсолютная частота кадров может быть выше, если вы запустите физическую подсистему для следующего кадра, пока подсистема рендеринга все еще работает на предыдущем Рамка. На самом деле, если у вас есть такие узкие места и вы не можете их устранить каким-либо другим способом, конвейерная обработка может быть наиболее законной причиной для беспокойства с потоками подсистемы.