게임 루프와 OpenGL 간의 멀티 스레딩 활용


10

openGL 렌더러를 기반으로 게임의 맥락에서 말하기 :

두 개의 스레드가 있다고 가정 해 봅시다.

  1. 게임 내 오브젝트에 대한 게임 로직 및 물리 등을 업데이트합니다.

  2. 게임 객체의 데이터를 기반으로 각 게임 객체에 대해 openGL 그리기 호출을 만듭니다 (스레드 1이 계속 업데이트 함)

게임의 현재 상태에서 각 게임 객체의 복사본이 두 개가 아닌 한 스레드 2를 그리는 동안 스레드 2를 일시 중지해야합니다. 그렇지 않으면 게임 개체가 해당 개체에 대한 그리기 호출 도중 업데이트됩니다. 바람직하지 않습니다!

그러나 스레드 1에서 스레드 호출을 안전하게 호출하기 위해 스레드 1을 중지하면 멀티 스레딩 / 동시성의 전체 목적이 중단됩니다.

멀티 코어 아키텍처를 사용하여 성능을 향상시킬 수 있도록 수백 또는 수천 또는 동기화 객체 / 울타리를 사용하는 것 외에 다른 방법이 있습니까?

현재 게임 상태에 아직 포함되지 않은 오브젝트의 텍스처로드 및 쉐이더 컴파일에 멀티 스레딩을 계속 사용할 수 있지만 그리기 및 업데이트와 충돌하지 않고 활성 / 표시 가능한 오브젝트에 대해 어떻게해야합니까?

각 게임 개체에서 별도의 동기화 잠금을 사용하면 어떻게됩니까? 이렇게하면 모든 스레드가 전체 업데이트 / 그리기주기가 아닌 하나의 객체 (이상적인 경우)에서만 차단됩니다! 그러나 각 객체를 잠그는 데 얼마나 많은 비용이 듭니까?


1. 단지 두 개의 스레드가 제대로 확장되지 않는다고 가정하면 4 개의 코어가 매우 일반적이며 증가 할 것입니다. 2. 모범 사례 전략 답변 : 명령 쿼리 책임 분리 및 액터 모델 / 컴포넌트 엔터티 시스템 적용. 3. 현실적인 답변 : 자물쇠와 물건으로 전통적인 C ++ 방식을 해킹하십시오.
Den

하나의 공통 데이터 저장소, 하나의 잠금 장치.
Justin

@justin 내가 동기화 잠금으로 말한 것처럼 멀티 스레딩의 유일한 장점은 일광에서 잔인하게 살해 될 것입니다. 업데이트 스레드는 스레드가 모든 객체를 호출 할 때까지 기다려야합니다. 그런 다음 업데이트 루프가 업데이트를 완료 할 때까지 기다립니다. ! 이것은 단일 스레드 접근 방식보다 나쁩니다
Allahjane

1
그것은 비동기 그래픽 API (예를 들어, OpenGL을)와 경기에서 멀티 스레드 방식처럼 보인다는 여전히 활성 주제이며, 표준 또는 거의 완벽한 해결책이 없다
Allahjane

1
엔진과 렌더러에 공통적 인 데이터 저장소는 게임 객체가 아니어야합니다. 렌더러가 가능한 한 빨리 처리 할 수있는 표현이어야합니다.
Justin

답변:


13

잠금을 사용하여 설명한 접근 방식은 단일 스레드를 사용하는 것보다 비효율적이고 속도가 느릴 수 있습니다. 각 스레드에 데이터 복사본을 유지하는 다른 방법은 "속도에 따라"잘 작동하지만 복사를 동기화하기 위해 메모리 비용과 코드 복잡성이 엄청나게 높습니다.

이것에 대한 여러 가지 대안이 있습니다. 멀티 스레드 렌더링에 널리 사용되는 솔루션 중 하나는 이중 버퍼 명령을 사용하는 것입니다. 렌더러 백엔드를 별도의 스레드에서 실행하여 렌더링 API와의 모든 그리기 호출 및 통신이 수행됩니다. 게임 로직을 실행하는 프론트 엔드 스레드는 명령 버퍼 (더블 버퍼) 를 통해 백엔드 렌더러와 통신합니다.. 이 설정을 사용하면 프레임 완료시 하나의 동기화 지점 만 있습니다. 프론트 엔드는 하나의 버퍼를 렌더 명령으로 채우고 있지만 백엔드는 다른 버퍼를 소비합니다. 두 실의 균형이 잘 잡히면 아무도 굶어 죽지 않아야합니다. 그러나이 방법은 렌더링 된 프레임에 대기 시간이 생겨 OpenGL 드라이버가 이미 자체 프로세스에서이 작업을 수행하고 있으므로 성능 향상을 신중하게 측정해야하기 때문에 차선책입니다. 또한 최대 2 개의 코어 만 사용합니다. 이 접근법은 Doom 3Quake 3 과 같은 여러 성공적인 게임에서 사용되었습니다.

멀티 코어 CPU를 더 잘 활용하는 확장 가능한 접근 방식은 독립적 인 작업을 기반으로하는 방법으로 , 보조 스레드에서 서비스되는 비동기 요청을 발생시키는 반면 요청을 발생시킨 스레드는 다른 작업을 계속합니다. 잠금을 피하기 위해 다른 스레드와의 종속성이없는 것이 이상적입니다 (전염병과 같은 공유 / 전역 데이터도 피하십시오). 작업 기반 아키텍처는 컴퓨팅 애니메이션, AI 경로 찾기, 절차 생성, 장면 소품의 동적 로딩 등과 같은 게임의 현지화 된 부분에서 더 유용합니다. 게임은 자연스럽게 이벤트가 가득하고 대부분의 이벤트는 비동기식이므로 별도의 스레드에서 실행하기 쉽습니다.

마지막으로 다음을 읽는 것이 좋습니다.


그냥 궁금 해요! Doom 3에서이 방법을 어떻게 사용했는지 어떻게 알 수 있습니까? 개발자가 기술을 절대로 내놓지 않았다고 생각했습니다!
Allahjane

4
@Allahjane, Doom 3은 오픈 소스 입니다. 내가 제공 한 링크에서 게임의 전체 아키텍처에 대한 리뷰를 찾을 수 있습니다. 그리고 완전히 오픈 소스 게임을 찾는 것은 드물지만 개발자는 일반적으로 블로그, 논문 및 GDC 와 같은 이벤트에 기술과 요령을 노출합니다 .
glampert

1
흠. 이것은 굉장한 읽기였습니다! 알려 줘서 고마워! 당신은 진드기를 얻는다 :)
Allahjane
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.