프로그래밍 언어 입문서가 아닌 프로그래밍 기초 개념 입문서
문과생, 비전공자를 위한 프로그래밍 입문책입니다.
jobGuid 꽃미남 프로그래머 "Pope Kim"님의 이론이나 수학에 치우치지 않고 실무에 곧바로 쓸 수 있는 실용적인 셰이더 프로그래밍 입문서 #겁나친절 jobGuid "1판의내용"에 "새로바뀐북미게임업계분위기"와 "비자관련정보", "1판을 기반으로 북미취업에 성공하신 분들의 생생한 경험담"을 담았습니다.
Posted by 랩.좀비

안녕하세요. 랩하는 좀비. 랩좀비입니다. 실제로 랩은 잘 못합니다. 뭐 중요한 것은 그게 아니고.

DOD에 대해서는 많이들 들어보셨을 겁니다. 

2010말에 DICE와 너티독 형님들에 의해서 체계적으로 정리 되어 발표 되었고, 작년 초에는 한국에도 소개가 많이 되어서 이런 저런 논의가 있었습니다. 적어도 작년말까지만 해도 꽤 활발한 토의가 진행되었었죠. 하지만 지금은 별 다른 이야기가 없어요. -이제 논의자체가 할 게 없는 것인가? 라는 생각도 듭니다.- 그냥 저렇게 하면 괜찮다. 하지만 적용 하기에는 좀 힘들지 않을까? 가 주된 내용인 것 같습니다.

OOP와 분리해서 생각 한다면 적용하는 것에 큰 문제는 없는 것 같습니다. 
이 글에서는 DOD의 복습과 어떻게 적용하였는지, 적용한 후에 프로그램은 얼마만큼 빨라졌는지에 대해서 얘기해 볼까 합니다.

DOD란?
...사실 새로 적을 것도 없기에 링크로 대체합니다.
친절한티스님의 글 : http://kindtis.tistory.com/341
김학규님의 글 : http://www.lameproof.com/index.php?mid=neolith&document_srl=174115
작년에 발표한 슬라이드 : http://www.slideshare.net/hyurichel/data-oriented-design-8284688
최근 이것과 관련해서 글을 써보자 하는 계기가 된 슬라이드 : http://www.slideshare.net/ssmim101/data-oriented-design-13941654

순서대로 읽으시면 쉽게 DOD가 무엇인지 파악할 수 있습니다.
간단히 요약하자면 배열로 잡아버리고 한번에 Update를 하자. 가 되겠습니다.

적용해보자
DOD는 대규모 데이터를 처리하는 데 가장 좋은 방식입니다.
게임에서 대규모로 처리할 부분이 있다면? 여기서는 Rendering Material들의 Update와 옥트리 컬링을 대표적인 예로 들까 합니다.

1. Material 업데이트
게임에서 렌더링되는 오브젝트들은 자신의 Material을 알고 있습니다. 그리고 Material이 시간에 따라 변화하게 된다면 당연히 CPU에서 해당 정보를 Update하여 Shader에 알려주어야 하지요. 이 Update하는 것을 OOP관점에서 디자인 한다면...

이렇게 되겠습니다. 지금까지 다들 그래왔고, 이것이 진리라고 생각했을 겁니다. ...나만 그랬나. 이런 구조를 만들어 놓으면 새로운 타입의 Material이 추가되어도 Update하는 방식은 외부에서 몰라도 되는 아주 OOP적인 디자인입니다.

이것을 DOD형태로 바꾸어 볼까요?


그림이 개발새발이지만 잘 아시리라 믿습니다.

이렇게 되겠습니다. 기본 구조는 똑같습니다. OOP의 장점을 버릴 수는 없습니다. 렌더링용 Material은 커다란 Pool에서 관리하도록 하고 CType1과 CTyp2는 포인터만 들고 있습니다. Pool에서 삽입과 삭제만 상수시간으로 결정할 수 있다면 성능 저하도 없습니다. 새로운 머터리얼 타입이 추가되어도, OOP의 이점으로 클래스를 추가하고 Pool에서 새로운 데이터 타입만 만들어주면 됩니다.

그럼 얼만큼 빨라졌을까요?


OOP의 Update. 0.41866ms가 소모됩니다.


DOD할 때는 0.23460의 시간이 소모되었습니다.

기본 2~3배 정도 속도향상이 됩니다.
의외로 성능향상이 별로 없습니다. 하지만 DOD의 이점은 Thread와 결합할 때 빛을 발합니다. 
OpenMP를 이용하여 적용해 보았습니다.

그냥 DOD Pool에서의 Update. 2.40707


Thread로 돌렸을 때, Core가 100%로 돌아가고 있습니다. 0.56839

5배 정도 성능이 향상되었네요. OOP에서 DOD로 2배. DOD에서 DOD_Thread로 5배.
총 10배의 성능이 향상되었습니다.
게임에 적용된다면 OOP보다 적어도 4-5배는 더 빨라졌을 것이라고 예상됩니다.


2. 옥트리 컬링
화면에 보이는 오브젝트를 걸러내기 위해서 옥트리 컬링을 하고 있습니다. ...이것도 DOD형태로 바꿔봅시다.
바꾸는 형식은 위의 Material 업데이트를 참고해서 하면 될 것 같습니다.

스크린샷은 올릴 수가 없기 때문에 그냥 글로써 얘기하자면, 옥트리와 비슷하거나 2-3배 정도 빠릅니다.
옥트리는 카메라의 위치에 따라서 속도의 변동이 있고, DOD는 속도의 변동이 없습니다.
또다른 이점으로 캐릭터나 Effect, Sound등등도 같이 한 번에 묶어서 컬링할 수 있기 때문에 좀 더 많은 성능 향상이 있었습니다.

결론

대규모 데이터를 처리할 때 DOD만큼 좋은 것은 없는 것 같습니다. Pool에서 삽입삭제만 상수시간으로 가능하다면 꽤 멋진 디자인입니다. Thread도 Lock-Free로 돌아가니 뭔가 한 듯한 기분도 듭니다. 결과적으로 좀 짱인 것 같습니다.

여러분도 적용해 보아요.

댓글을 달아 주세요

  1. Favicon of http://bluekms21.blog.me 크로스 2012.10.07 21:16  댓글주소  수정/삭제  댓글쓰기

    DOD를 '여러분도 적용해 보아요.'라는 밝은 마무리로 끝내시다니.. ㅇ<-<
    저도 김학규님의 글만 접하고 개념정도만 알고 있었는데
    두번째 자료를 보니 무척 매력적이고 당장이라도 적용할 수 있을것만 같군요~!
    하지만 세번째 링크를 보니 '역시 일단 OOP나 잘 해보자...' 라는 생각을.. ㅇ<-< ㅋ

    • Favicon of https://gamedevforever.com 랩.좀비 2012.10.08 14:30 신고  댓글주소  수정/삭제

      어떻게 적용하는지는 다 서술했다고 생각합니다=ㅅ=. 하위 클래스들이 갖고 있는 데이터를 한 곳에 묶고 Update를 그 쪽에서 하는 게 핵심입니당. 의외로 쉬워요.