학계 최악의 경우 Big O 는 다른 모든 것에 대해 가르쳐집니다. 공간 복잡성, 일반 사례 분석, 복잡성에 대한 단순성 등과 비교
특히 게임 프로그래밍 및 산업 분야에서 가장 중요한 것은 무엇이고 왜 그런가?
참조는 매우 도움이 될 것입니다.
학계 최악의 경우 Big O 는 다른 모든 것에 대해 가르쳐집니다. 공간 복잡성, 일반 사례 분석, 복잡성에 대한 단순성 등과 비교
특히 게임 프로그래밍 및 산업 분야에서 가장 중요한 것은 무엇이고 왜 그런가?
참조는 매우 도움이 될 것입니다.
답변:
"하나의 진정한 경로는 무엇인가"에 관한 다른 모든 질문 과 마찬가지로 , 이들은 도구 상자의 모든 도구이며 big-O가 모든 것을 능가하는 경우와 중요하지 않은 장소가 있습니다 (tm).
당신은 big-O에 대해 걱정하지 않고 물리 솔버를 "절대로"쓰지 않을 것입니다. 염려하지 않고 정렬 알고리즘 (최소한 데이터 집합을 제외하고)을 구현하지 않을 것입니다. 네트워크 게임을 작성하는 경우 성능 및 네트워크 트래픽이 사용자 당 확장되는 방식에 관심이 있습니다.
글쎄, 나는 정말로 시간을 생각할 수 없지만 몇 가지가 있다고 확신 할 때 big-O에 대해 그렇게 걱정하지 않을 수도 있습니다. 고맙게도, 우리가 게임에서하는 대부분의 일은 선형 적으로 확장됩니다. 디스크에서 파일을 읽고 싶습니까? 파일 크기에 선형 적으로 비례하는 시간이 필요합니다 (구속적인 크기의 탐색 및 가능한 섹터 크기의 영향을 무시 함).
그러나 엔터티 목록에서 특정 엔터티를 찾으려면 어떻게합니까? 그것은 당신이 그것을 할 때마다 선형 검색입니다. 전 세계의 모든 엔티티에 대해 플레이어를 한 번 찾아야하는 경우,이 방법을 사용하면 가장 사소한 게임을 제외한 모든 플레이어를 죽일 수 있으며,이 조회를 일정 시간으로 "최적화"하는 것이 좋습니다 (예 : 색인을 저장) 또는 플레이어를 가리키는 포인터)를 통해 실제로 플레이어에게 표시되는 다른 작업을 수행 할 수있는 더 많은 시간을 제공합니다.
그래도 요약하자. 프로세서가 플레이어에게 직접 표현할 수없는 무언가를 할 때마다 시간을 낭비하고 있습니다. 프로세서가 플레이어에게 보여줄 데이터를 계산하는 시간을 최대화하면 WOW!당신은 플레이어를 제공하고 있습니다.
경험상 O (무서운)가 아닌 한 다른 문제는 더 적절합니다.
경험의 또 다른 규칙은 데이터가 왕이라는 것입니다. 현실적인 데이터 세트로 코드를 프로파일 링하지 않으면 추측 할 수 있습니다.
편집 : 좀 더 자세히 설명하기 위해 (적어도 내 경험으로는) 대부분의 데이터 세트가 상대적으로 작기 때문에 큰 O는 그렇게 중요하지 않습니다. 수백 개 미만의 요소가있는 데이터 구조로 작업 할 때는 성능의 상한에 신경 쓰지 않을 것입니다. 그리고 목록에 100k + 요소가 있다면 알고리즘의 모든 측면을 고려해야합니다. 내 경험에 따르면 메모리는 CPU 속도보다 제한적인 요소입니다. 빠른 메모리 호깅 알고리즘은 사용 사례에 따라 더 적지 만 느릴 수 있습니다.
Big O는 대부분 중요하지만 때로는 이론 상으로는 "더 나쁜"알고리즘이 실제로 훨씬 빠르다는 것이 밝혀졌습니다.
Tony Albrecht의 훌륭한 예를 확인하십시오. http://seven-degrees-of-freedom.blogspot.com/2010/07/question-of-sorts.html
게임 개발에서 조작의 항목 수가 너무 커서 매우 다른 알고리즘이 더 빠르거나 너무 작고 멍청한 알고리즘이 충분하거나 캐시에 잘 맞아 효율성을 무시하는 게임 개발의 모든 곳에서 이것이 발견됩니다. 의 더 나은 알고리즘).
Big O의 문제점은 일반적인 작업 복잡성 지정이며 최신 대상 하드웨어의 복잡성을 고려하지 않으며 설정 시간 오버 헤드에 대한 통찰력도 제공하지 않는다는 것입니다.
대부분의 경우 최상의 최적 솔루션은 두 단계입니다. 실제로 게임 개발자는 O 알고리즘이 낮은 경향이 있지만 개발 또는 디버깅에 소요되는 비용과 균형을 이룹니다. 합리적인 솔루션을 확보 한 후에는 항상 하드웨어가 작업을 처리하는 방법과 적은 시간에 하드웨어를 더 잘 처리하는 방법을 살펴 봐야합니다.
나는에 엔진 코딩있을 때, 나는 종종 고정으로 걱정 n
: 이미 수신 객체의 수를 제한 공간적 분할있어 update()
, physics()
및 render()
화면 및 주변 지역에 약에게 있습니다. 최대 배치 크기는 일반적으로 게임마다 잘 정의되어 있지만 계획 한 것보다 약간 큽니다.
이 경우 상수 인수 승수 및 하위 차수에 관심이있는 것처럼 big-O에 대해서는 크게 관심이 없습니다. a*n^2 + b*n + c
( 와 같은) 런타임을 가진 함수의 O(n^2)
경우 종종 축소에 더 관심이 있습니다.a
및 제거에 있습니다 c
. 설치 또는 분해 비용 c
이 비례 적으로 커질 수 있습니다 n
.
그러나 이것은 big-O (또는 더 구체적으로 big-theta )가 훌륭한 코드 냄새 표시기 . O(n^4)
어딘가 또는 더 나쁜 것을 보아라 .O(k^n)
기하학적 시간을, 그리고 그것의 시간은 당신이 고려하고 다른 선택을 할 수 있습니다.
나는 일반적으로 데이터 제작 도구를 다룰 때 big-O 최적 성과 더 큰 bigO를 가진 알고리즘을 찾기 위해 농구를 뛰어 넘습니다. 주어진 레벨 / 스트리밍 영역의 오브젝트 수는 일반적으로 잘 정의되어 있지만 전체 게임에서 오브젝트 / 아트 자산 / 구성 파일 등의 총 수는 그렇지 않을 수 있습니다. 또한 더 큰 숫자입니다. 병렬 데이터 메이크를 실행하더라도, 우리는 여전히 1 분 정도 기다립니다 jam data-clean && jam data
.
구체적인 예를 들자면, 이것은 8x8 256 색 타일을 스트리밍하는 배경 타일 스트리밍 알고리즘을 사용하지 않는 것입니다. 백그라운드 "레이어"간에 스트리밍 버퍼를 공유하는 것이 유용하며, 동일한 레벨을 공유하는 주어진 레벨에서 최대 6 개를 가질 수 있습니다. 문제는 필요한 버퍼의 크기를 추정하는 것이 6 개의 모든 레이어의 가능한 위치를 기반으로하고 소수의 너비 / 높이 / 스크롤 속도 인 경우 신속하게 철저한 검색을 시작한다는 것입니다. 접근 시작O(6^numTiles)
많은 경우 "우주보다 더 긴"범주에 속합니다. 운 좋게도 대부분의 경우는 2 ~ 3 개의 레이어이지만 30 분 이상 실행됩니다. 현재 우리는 이러한 가능성의 매우 작은 부분 집합을 샘플링하여 정해진 시간이 지날 때까지 세분성을 증가시킵니다 (또는 작은 이중 계층 구성에서 발생할 수있는 작업을 완료했습니다). 우리는 얼마나 자주 잘못 확인되었는지에 대한 사전 통계를 기반으로이 추정치를 조금 올린 다음, 좋은 측정을 위해 약간의 추가 패딩을 추가합니다.
또 다른 재미있는 예 : PC 게임에서 잠시 후 수석 엔지니어는 건너 뛰기 목록 으로 잠시 실험했습니다 . 메모리 오버 헤드로 인해 더 많은 캐시 효과가 발생하여 전체적으로 일정하지 않은 승수가 추가되므로 실제로 작은 선택에는 적합하지 않습니다 n
. 그러나 검색이 자주 발생하는 더 큰 정렬 된 목록의 경우 이점이 있습니다.
(나는 종종 순진한 알고리즘이 더 큰 O, 더 작은 데이터 세트에서 더 빠르며 이해하기 쉽다는 것을 발견합니다. 더 흥미롭고 복잡한 알고리즘 (예 : patricia trie)은 사람들이 이해하고 유지하기가 더 어렵지만 더 큰 성능은 더 높습니다 데이터 세트.)
편리 할 수도 있지만 관련이 없을 수도 있습니다. 예를 들어 Smash TV 클론의 가장 최근 게임을 예로 들어 보겠습니다. 하향식 게임, 측면에서 몬스터가 쏟아져 나옵니다.
이제 충돌을 결정하는 영리한 방법이 많이 있습니다. KDtrees를 사용하여 공간을 분할하여 적을 칠 수없는 몬스터에 대해 총알을 테스트하지 않습니다. 그리고, 나는 영리했고, 그렇게 할 수있었습니다.
그러나 나는 게으른 느낌이 들기 때문에 모든 총알과 모든 괴물을 비교했습니다. 가장 열악한 상황에서도 충돌 코드는 60fps에서 게임 CPU의 10 % 미만을 사용하고있었습니다. Big-O : 중요하지 않습니다.
마찬가지로, 나는 당신이 섬에 도시를 짓는 4x 스타일의 게임을 가지고 있었고 때로는 도시가 파괴되었습니다. 나는 영리하고 파괴 된 도시의 소득을 소득 변수에서 빼려고 노력할 수있었습니다. 그러나 나는하지 않았다. 방금 소득이 없어지고 무언가가 바뀔 때마다 처음부터 다시 계산했습니다. CPU와 관련이 없습니다.
Big-O는 다른 모든 것만큼이나 게임에서 중요합니다. 즉, 중요하지 않을 때까지는 중요하지 않습니다.
가서 코드를 작성하십시오. 너무 느리면 프로파일 링하십시오.
Big-O 분석은 중요하지만 게임 개발에서 가장 먼저 생각하는 것은 아닙니다. 게임에 복잡한 코드가 많이 포함되므로 항상 권장합니다 알고리즘의 첫 번째 기준으로 코드 단순성 을 합니다. 복잡한 부기 기능이있는 알고리즘은 시간을 낭비합니다.
개발하는 동안 게임이 항상 60fps로 실행되는 것이 중요하다고 생각합니다. 그 아래로 몸을 담그면 가장 먼저 프로파일 러를 실행해야합니다. 병목 현상을 찾으면 공격합니다. 레벨 디자이너에게 영역에 더 적은 수의 물건을 넣고 도구를 제공하도록 지시하는 것과 같이 비 코딩 작업을 수행해야하는 경우가 많습니다.
때로는 실제로 속도를 높여야하는 일부 코드를 식별 할 수 있습니다. 나는 이것이 재미있는 공학이라고 생각한다! 더 많은 기회가 있었으면 좋겠습니다. 물론 한 번에 하나씩 변경하고 성능을 측정하고 싶습니다. 내가 찾은 팁 문제는 다음과 같습니다.
Big-O는 단지 지침 일뿐입니다. 알고리즘에서 기대할 수있는 대략적인 성능을 알려주고 데이터 세트의 크기를 늘릴 때 어떻게 성능을 확장해야하는지 알려줍니다 . Big-O와 관련하여 두 가지 주요 사항을 기억해야합니다.
1) 대부분 동일한 작업을 수행하지만 하나는 더 나은 O를 갖는 두 개의 알고리즘이있는 경우 아마도 그 알고리즘을 사용해야합니다 (분명히)
2) Big O는 점근 분석 과 관련이 있습니다. Big-O 는 n이 클 때만 실제로 작동 합니다. 예를 들어, O (n) 알고리즘은 성능이 작은 n에 대해 O (n ^ 2) one과 매우 유사 할 수 있습니다 . 정점 당 n ^ 2 연산이 필요하지만 n = 2 또는 n = 3 인 알고리즘에 대해 이야기 하는 경우 O (n ^ 2) 알고리즘 (4 및 9 ops resp) 사이에는 큰 차이 가 없습니다. O (n) one (2 및 3 ops resp.). 그러나 n = 9 인 경우 갑자기 O (n ^ 2) 알고리즘의 경우 81 개의 연산에 대해 이야기하고 O (n)의 경우 9 개의 연산 (더 큰 차이)과 n = 100 인 경우 10000 대 10000에 대해 이야기하면 훨씬 더 큰 차이가 있습니다.
따라서 항상 이러한 관점에서 Big-O를 고려해야합니다. 이는 n이 커질 때 최악의 성능 을 기반으로 동일한 작업을 수행하는 알고리즘을 비교하는 것 입니다. n이 매우 작은 경우 알고리즘 간의 차이는 무시할 수 있습니다.
나는 언급이 없지만 문제와 토론을 분석 할 때 Big O는 알고 있어야합니다. 반면에, O (log n) 버전이 O (n) 버전보다 O와 관련이 더 많은 방법을 가지고 있다면 모순 비교입니다. 그리고 모든 것과 마찬가지로 항상 상충 관계가 있습니다. 공간 복잡도는 문제가 될 수 있지만 일반적으로 O로 표현 될 수 있습니다. 일반적인 사례 분석 ... 그렇지 않으므로 특이 치가 급증하지 않기를 바랍니다. 제 생각에 복잡성에 대한 단순성은 속도가 거의 항상 문제이기 때문에 게임 개발에서 상대적으로 쓸모가 없습니다. 따라서 단순성이 속도 향상으로 이어지지 않는 한 (그러나 복잡한 사유가 잘못된 이유로 잘못되었다는 의미) 단순성은 가야합니다. 속도를 위해 창 밖으로. 그러나 Big O는 확실히 유용합니다.
게임 기능이나 게임의 특징을 프로토 타이핑 할 때 전혀 최적화하지 않아도 됩니다 .
그것을 프로토 타이핑하고 그 기능의 특유성에 대해 배우는 과정에서 필요한 최적화가 명백 해지고 2 차 자연과 같은 최종 디자인을 고려할 것입니다.
땀 흘리지 마
전부가 아니고 끝이 아니어야합니다. 그러나 성능 저하를 일으킬 수있는 명백한 문제를 해결하는 데 도움이됩니다. O (log n) 시간에 같은 일을 할 수 있는데 왜 O (n ^ 2) 시간에 무언가를 사용 하는가?
시장은 속도 문제를 가장 많이 인식하는 시장이기 때문에 다른 산업보다 게임에 더 많이 적용됩니다. 워드 프로세서를 사용하는 사람은 액션 X를 수행하는 데 0.5 초의 지연이 있는지 신경 쓰지 않지만 게이머는 아마도 'omg omg 게임 Y가 너무 느리므로 액션 Z를 수행하는 데 시간이 오래 걸립니다'.
게임 (및 대부분의 다른) 개발에서 루프 당 하나의 추가 작업이 수행됩니다.
for (int i = 0; i < array.length; i ++) { /* ... */ }
vs.
for (int i = 0, l = array.length; i < l; i ++) { /* ... */ }
대부분의 현대 게임에는 물리가 있으며 n-body 시뮬레이션 문제가 있습니다. 순진한 알고리즘에서는 O (n ^ 2)이지만 O (n log n)로 만드는 최적화가 있지만 정확도는 약간 떨어집니다.
당신은 중력과 입자 상호 작용을 프로그래밍하는 것이 아니라 다른 위치 (더 구체적 단어 : 떼거리)에 의존하는 군대 (좀비)의 팀 행동은 어떻습니까?
종래의 충돌 검출 알고리즘에서 시간 복잡도는 n-body와 같이 O (n ^ 2)이다. 그러나 더 좋은 방법이 있습니다. 세계를 여러 개의 작은 부품으로 분리하여 동일한 부품 내부의 물체 만 충돌을 감지합니다. http://www.videotutorialsrock.com/opengl_tutorial/collision_detection/text.php를 참조 하십시오 .
게임이 스크립트 가능한 경우, 스크립트에서 사용자의 가방 검색과 같은 O (n ^ 2) (및 최대) 숫자 크 런칭 알고리즘을 작성하지 마십시오. 대신 코드에 내장 함수를 작성하십시오.
실제 세계에서는 원시 성능 만 중요합니다. 이제 알고리즘의 Big-O는 무엇을 사용해야하는지에 대한 첫 번째 표시로 사용될 수 있지만 하드웨어에 따라 구현이 매우 비효율적 일 수 있습니다. 예를 들어 선형 검색은 선형 메모리 액세스 권한이 있고 분기가 없기 때문에 이진 검색보다 빠를 수 있습니다.
또한 멀티 스레드 플랫폼 및 아키텍처의 현재 방향으로 인해 Big-O는 알고리즘의 방법을 고려하는 대신 작업 당 메모리 또는 데이터 터치의 수직 확장 성을 고려하기 때문에 많은 중요성을 잃고 있습니다. 더 많은 수의 스레드로 확장됩니다.