멀티 코어와 메시징

멀티 코어는 여러 개의 쓰레드를 사용하게 된다. 이런 환경에서 가장 문제가 되는 것은 공유 데이터에 대한 접근 방법이다. 물리 시스템이 하나의 쓰레드를 사용하고 렌더링 시스템 역시 쓰레드를 사용하여 분리한 경우를 보자.

게임 루프에서 충돌이 일어난 후 물리 시스템은 충돌 이벤트에 대해서 게임 객체의 새로운 위치를 계산한다. 그리고 렌더링 시스템에서는 갱신된 새로운 위치 데이터를 사용하여 게임 객체를 렌더링한다. 그런데 이들 두 시스템이 각각의 쓰레드로 분리되어 실행되고 있다는 점이다.

일반적인 방법으로는 lock을 사용한다. 물리 시스템에서 게임 객체의 위치를 갱신하기 전에 다른 시스템에서 이 데이터에 접근하지 못하도록 lock을 건 다음 데이터를 갱신한다.

그런데 이 lock의 오버헤더가 만만치 않다. 또 이런 식으로 lock/unlock을 사용하면 전체 시스템이 복잡해지는 것은 두말할 필요도 없다. 행여 실수로 lock/unlock을 빠뜨리는 경우 시스템은 예기치 않은 오동작을 하게 된다. 더 큰 문제는이 문제가 바로 쓰레드와 관련한 문제라는 것이다. 복잡한 시스템에서 쓰레드의 문제는 해결하기가 매우 어려운 경우가 대부분인데다 심지어는 재앙을 초래하기도 한다.

그럼, 쓰레드를 사용해서 동시에 여러 개의 시스템을 실행할 때 이들 시스템 간의 데이터 공유 문제에 해결에는 어떤 방법이 좋을까?

바로 데이터를 복사하는 방법이다. 이것은 시스템이 서로 다른 시스템의 데이터에 접근하는 방법이 아니라 각 시스템이 시스템 내부에 공유 데이터의 복사본을 가지고 있고 메시지를 통해서 다른 시스템에 자기 시스템에서의 공유 데이터의 변경을 알리는 방법이다.

쓰레드 A에서 쓰레드 B의 함수를 바로 호출하는 방법도 사실은 다른 시스템의 데이터에 lock을 통해서 바로 접근하는 방법에 속한다. 메시지를 통해서 공유 데이터를 복사하는 방법은 이러한 lock을 사용할 필요가 없거나 혹은 최소한의 lock이 필요할 따름이다. 메시지는 특별한 형태가 아니라 일반적으로 알고 있는 바와 같이 다음과 유사한 형태로 처리할 수 있다.

...
//메시지 생성
Message::MoveMsg moveMsg = Message::MoveMsg::Create();

//메시지 값의 설정
moveMsg.Set(x, y, z);

// 메시지의 전송
moveMsg.SendAsync();
...

일전[1]에 망갈로 게임 프레임워크의 메시지 시스템의 장점 중에 하나로 멀티 코어 시스템에 편리하다고 이야기한적이 있었는데 바로 이런 이유에서다. 또 이렇게 메시지를 사용하게 되면 각 시스템을 서로 완전히 분리(decoupling) 시킬 수가 있는데 이것 역시 멀티 코어를 사용하여 각 시스템들을 동시에 실행시킬 때에는 매우 중요한 것 중의 하나이다.

컴포넌트 방식의 게임 프레임워크[2]에서 컴포넌트 간의 통신에 메시지를 사용하게 되면 이처럼 멀티 코어 환경에서도 잘 작동하는 유용하고 견고한 시스템의 설계가 가능하다.


[1] KGC 2008, Nebula2 Mangalore Game Framework에서
[2] GPG6, Component based Game Framework Library


...이렇게 메시지를 사용하게 되면 이제 메시지 전달의 순서에 대한 문제가 대두됩니다. 무슨 말이냐 하면 물리 시스템의 위치 메시지는 렌더링 시스템의 위치 메시지보다 먼저 처리되어야 합니다. 바꾸어 말하면 물리 시스템에서 계산된 위치 데이터를 계산한 다음 이 메시지가 렌더링 시스템에 전달되어야 순서에 맞습니다다. 이 부분은 또 다음에... ^^

by kimsama | 2009/05/03 18:17 | MultiCore | 트랙백 | 덧글(7)

트랙백 주소 : http://kimsama.egloos.com/tb/1901538
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by 버츠 at 2009/05/03 19:50
Nebula3 를 틈틈히 보고 있습니다....
시스템 전체가 저런 방식으로 일관성 있게 디자인 되어있더군요. 많은 것은 배우고 있습니다.
(메인 개발자분인 floh 님도 참 대단한 듯...)
Commented by kimsama at 2009/05/04 12:31
네, N3부터는 처음부터 멀티코어를 고려해서 새로 설계, 작성했죠. 아직까지 본 코드 중에서는 게임용 멀티코어 아키텍쳐로는 가장 훌륭해 보입니다.
Commented by rein at 2009/05/03 21:09
메시징은 게임 뿐만 아니라 여러 개의 연산 장치를 쓰는 방식에선 참 편리한(?) 동기화(??) 방법인듯합니다.

lock-ordering때문에 머리아프던 문제가 메시징을 쓰면 깔끔하게 풀리는 경우가 참 많더라고요~_~
Commented by kimsama at 2009/05/04 12:58
게임도 여러 개의 연산 장치(?)들로 구성되어 있긴 합니다. 물리, 렌더링, AI 등등... 결혼 축하합니다. 5월에 결혼시는군요, 신부님이 좋아하시겠어요~ ^^
Commented by 버츠 at 2009/05/08 18:16
그런데 Nebula 3 에 아직 렌더링 소팅관련 내용이 아직 업데이트 안된건가요?
framebatch 쪽이랑 visResolver 쪽을 봐도 관련된 SortingMode 열거체는 있는데 딱히 적용하는 코드가 안보이네요.. 제가 못 찾는건지 ^^;; ㅎㅎ
Commented by 버츠 at 2009/05/08 18:17
아, Model 별로 묶어서 렌더링 하도록 되어있긴 하더라구요. 그런데 framebatch 에서 정렬관련 정보들은 갖고 있는데 따로 적용하는 부분이 없는 거 같아서 혹시 아시면 알려주세요 ^^;;
Commented by kimsama at 2009/05/11 11:30
짧게 결론만 말씀드리면 아직 진행 중이라서 소팅쪽이 완전하지 않은 것이 맞습니다. 덧글에 달면 주저리 주저리 길어질 것 같아 따로 한번 포스팅을 하겠습니다. 그럼~ ^^

:         :

:

비공개 덧글

◀ 이전 페이지다음 페이지 ▶