Upload
romanlut
View
710
Download
0
Embed Size (px)
DESCRIPTION
Презентация заняла второе место в Intel Game Demo 2008 contest.
Citation preview
Внедрение параллельного
рендеринга в игровой движок
Роман Лут,Ведущий программист,
Deep Shadows
Кратко о себе
Распараллеливание – необходимость: “Free lunch is over”
Минимальная конфигурация – Core 2 Duo, “обычные” игры используют 50% CPU
Ведение
Создаем несколько потоков и делаем в них что-нибудь
«Плохая» многопоточность
Результат: полная неразбериха, ничего не работает
Распараллеливанию программы мешает её линейный характер исполнения - следующий блок использует данные, созданные предыдущим.
Первый шаг: анализ системы, разделение ее на относительно независимые компоненты с минимальным, с четко описанным взаимодействием.
Выбор модели распараллеливания
Анализ, разделение
Модель 1: Независимые компоненты движка работают в разных потоках
Рендеринг игрового мира
Апдейт состояния игрового мира
Апдейт состояния игрового мира
Апдейт состояния игрового мира
Рендеринг игрового мира
Рендеринг игрового мира
+ относительно простая реализация, но при наличии достаточно независимых компонентов.
+ простое и понятное взаимодействие компонентов в параллельном приложении
- плохая масштабируемость вверх- необходимость хранения двух состояний
мира (готовое, и текущее рассчитываемое - аналогично front и back buffers в графике).
- отсутствие балансировки загрузки ядер (одна из систем всегда будет ожидать другую).
Модель 1: Плюсы и минусы
Модель 2: Producer - consumer
Рендеринг объекта
Апдейт объекта
+ относительная простота реализации
+ сохраняется линейная логика исполнения программы
+ возможность реализации дополнительной функциональности (сортировка по render states)
- плохая масштабируемость- отсутствие балансировки загрузки
ядер
Модель 2: Плюсы и минусы
Модель 3: Расщепление нити исполнения
Block 2
Block 3
Block 4
Block 2
Block 3
Block 4
Block 1
Block 1
Sync
+ сохраняется относительно линейная последовательность исполнения
+ относительно простая реализация в существующем коде
- возможности оптимизации ограничены
- неэффективная загрузка ядер
- плохая масштабируемость вверх
Модель 3: Плюсы и минусы
Модель 4: Task dependency graph
Block 2
Block 8
Block 4
Block 1
Block 5
Block 7
Block 3
Block 6
Block 10
Block 9
+ отличная масштабируемость+ максимально эффективная загрузка
доступных ядер+ можно расширить систему, добавив
задачи для SPU, CUDA. - "динамическая система" со всеми
свойственными недостатками: - непредсказуемый порядок исполнения; - сложность отладки - требует полного пересмотра архитектуры
движка (нужно переписать все "с нуля")
Модель 4: Плюсы и минусы
Для справки: от момента создания потока до начала его выполнения может пройти до 100 мс
Нужна библиотека более высокого уровня
Задачи в ITBB: tbb::task.spawn(), tbb::task.waitforall()
+содержит контейнеры с поддержкой многопоточности, примитивы синхронизации, параллельные алгоритмы и т.д.
www.thredingbuildingblocks.org
Intel Threading Building Blocks
Никогда нет времени сделать все оптимально! ( реальность программирования ).
“Идеальное” решение не является требованием. Требование - обеспечить 30FPS с имеющимся контентом.
Producer-consumer и Расщепление нити исполнения не требуют глобального изменения кода.
Выбор архитектуры
Ситуация до оптимизации
Ситуация до оптимизации
Ситуация до оптимизации
Producer-consumer рендеринга
Обход сцены Апдейт мира
Ring buffer
Рендериг
Producer-consumer рендеринга
Producer-consumer рендеринга
Producer-consumer рендеринга
Результат: повышение FPS на
>150% !
Producer-consumer рендеринга: детали реализации
Очень не хочется перерабатывать весь код
Хочется оставить возможность рендерить по-старому
Решение: включение/отключение параллельного рендеринга «на лету»
Внутри методов API графической библиотеки либо записывать команды в Ring Buffer, либо выполнять сразу
Проверка условия: bParallelrenderingEnabled && GetCurrentThreadId() != RenderingThreadId
Producer-consumer рендеринга: детали реализации
В Ring buffer складываются классы, наследованные от TRBRecord, с помощью placement new()
Класс содержит в себе все параметры для вызова метода графического API
Метод Run() вызывает метод API Зацикливание не происходит
благодаря проверке GetCurrentThreadId() != RenderingThreadId
Producer-consumer рендеринга: детали реализации
void TRenderStateFactory::SetWorldMatrix(const TMATRIX4x3* matWorld)
{ if ( RenderLib.renderThreading.IsRecordingThread() ) { VE_FIRE_RING_BUFFER_EVENT_P(TRBRSetWorldMatrix,
matWorld); return; }
m_WorldMatrix = *matWorld;RenderLib.VertexShaderFactory.ConstantCache.InvalidateConst
ants(VSHC_WORLDVIEWMATRIX);}
Producer-consumer рендеринга: детали реализации
class TRBRSetWorldMatrix : public TRBRecord { public: TRBRSetWorldMatrix(const TMATRIX4x3* worldMatrix) { m=*worldMatrix; } virtual bool Run() { RenderLib.RenderStateFactory.SetWorldMatrix(&m); return true; } private: TMATRIX4x3 m; };
Producer-consumer рендеринга: выводы
«Однонаправленный» API – хорошая линия раздела для producer-consumer модели
Быстрая реализация, хороший результат
Глобальные переменные – враги распараллеливания
Emergent DirectX command buffer library
Producer-consumer для DirectX API
Используется в Gamebryo
Open Source library: http://www.emergent.net/GameFest20
08
Future work
Убрать глобальные переменные и контексты!
Расщепление нити исполнения, на основе tbb::task
Вопросы ? Intel Threading BuildingBlocks www.threadingbuildingblocks.org
Vincent Scheb, GameBrio, Emergent game technologies, “Practical Parallel rendering with DirectX 9 and 10”, http://emergent.net/GameFest2008
“Emergent open source Command Buffer library”, http://emergent.net/GameFest2008 Jim Tilander, Vassily Filippov, Sony Santa Monica, “Practical SPU Programming in God of War III” Capcom lecture, “Capcom MT framework”,
Capcom lecture, “Lost planet multithreaded rendering” Ville Mönkkönen , Gamasutra, “Multithreaded game engine architectures” Henry Gabb and Adam Lake, Gamasutra, “Threading 3D Game Engine Basics”
Jonathan Haas, Game Technology Group, Microsoft, "Designing Multi-Core Games: How to Walk and Chew Bubblegum at the Same Time“
Abdennour El Rhalibi, Dave England and Steven Costa, "Game Engineering for a Multiprocessor Architecture”
Tom Leonard, Valve, "Dragged Kicking and Screaming: Source Multicore“
Will Damon, Engineer Software Solutions Group, Intel Corporation "Multithreading Your Game Engine for Hyper-Threading Technology“
Leigh Davies, Senior Application Engineer, INTEL, "Optimizing DirectX on Multi-core architectures“
Maxim Perminov, Aaron Coday, Will Damon, "Real World Multithreading in PC Games Case Studies"