p.473 gpg gems8

어떠한 클래스 계통구조가 주어졌을 때, 클래스 A가 클래스 B의 하위 클래스(subclass)인지 알아내고자 할 때
아래가 전형적인 방법이다.
bool IsA( Class* pA, Class* pB )
{
while( *pA != NULL )
{
if( pA == pB )
{
return true;
}
pA = pA->GetParentClass();
}
}
이렇게 될 경우 운이 나쁘면 비교하는 작업의 시간이 길어질 수 있다.
프로젝트 막바지에 운이 좋게 아래와 같이 정확히 두개씩 자식노드가 분기되는 형태로 되었다고 가정하자.

이름 아이디 클래스색인
Object 1 수준1
Human 2 수준2
Weapon 3 수준3
Warrior 4 수준3
Mage 5 수준3
Sword 6 수준3
Bow 7 수준3
여기서 클래스 색인과 아이디를 이용해 반복문 없이 자식관계를 판정할 수 있다.
판정을 할 때 BitScanReverse 함수를 사용한다. 이 함수는 주어진 값의 비트들에서 제일 왼쪽에 있는 1비트의 위치를 돌려준다.
1 ( 10진수 1 ) -> 0
10 ( 10진수 2 ) -> 1
11 ( 10진수 3 ) -> 1
111 ( 10진수 7 ) -> 2
위의 균형잡힌 트리대로 노드가 구축되어 있다면 비트연산을 통해 부모관계를 판단하기가 쉽다.
위 노드들을 2진수로 표현해 보자.

여기서 BitScanReverse 를 이용해 부모관계를 판단해 보자.
우선 가장 위쪽에 있는 1을 BitScanReverse로 값을 받으면 0 이 나온다.
왼쪽에서 0번째 값이 1인 노드들은 최상위 1의 자식들이다.
그렇다. 여기 그림에 있는 모든 노드는 1의 자식이다. 왼쪽 0번째 값이 1이 아닌 값이 없기 때문이다.
그 다음으로 10으로 보자. 10진수로 2인데 BitScanReverse로 값을 받으면 1 이 나온다.
왼쪽에서 0번째, 1번째 값이 10 이면 10 의 자식이다. 여기서 100, 101 이 자식이 된다.
다음으로 11으로 보자. 10진수로 3인데 BitScanReverse로 값을 받으면 1 이 나온다.
왼쪽에서 0번째, 1번째 값이 11 이면 11의 자식이다. 여기서 110, 111 이 자식이 된다.
아래가 위 내용을 판단하는 코드이다.
bool FastIsA( Class* pA, Class *pB )
{
int nAIndex = pA->GetClassIndex();
int nBIndex = pA->GetClassIndex();
return nBIndex == ( nAIndex >> ( BitScanReverse(nAIndex) - BitScanReverse(nBIndex) );
}
위 경우는 반드시 균현잡힌 트리 구조일 때 사용이 가능하다. 하지만 모든 프로젝트에서 정보를 저렇게 구현한다고는
생각하기 어렵다.
그래서 균형 이진 트리가 아니더라도 허위 노드를 삽입해서 균형 이진트리 비슷한 모양을 구축하면 위 방법대로 사용할 수 있다.
자식노드의 개수와 레벨을 통해 허위 노드를 어떻게 만들지 판단한다.
void BuildTree( Class* pA )
{
int nCurrentClassIndex = pA->GetClassIndex();
int nNumChildClasses = pA->GetNumberOfChildClasses();
int nNumLevels = BSR(nNumChildClasses) + 1;
int nChildIndexStart = nCurrentClassIndex << nNumLevels;
for( int i = 0 ; i < nNumChildClasses ; ++i )
{
class* pChild = pA->GetChildClass( i );
pChild->SetClassIndex( nChildIndexStart + i );
BuildTree(pChild);
}
}
모양은 바꼈지만 위 방식대로 부모관계를 판단할 수 있는 기틀을 마련할 수 있다.

많은 곳에서 IsA를 이렇게 판단하고 있다면 이 방법을 적용해서 제법 속도향상을 기대할 수 있겠다.
요즘은 제너럴 프로그램을 통해 CPU속도를 빠르게 하는 방법에 대해 관심을 가지고 있어서
이러한 내용들을 계속 공부해 보려 한다.
그리고 요즘 게임에서 돈잔치를 벌이는데 있어 유용한 기술의 보조작업을 하고 있다.
알고리즘 적으로 막히는 부분은 다 해결되서 상당히 기쁘다.
그리고 아래는 라이트 셰프트를 어떻게 해서든 적용해 보고싶은 개발자 아버지를 둔 가정의 흔한 식사 모습.

라이트 셰프트도 마저 해야 하는데........

어떠한 클래스 계통구조가 주어졌을 때, 클래스 A가 클래스 B의 하위 클래스(subclass)인지 알아내고자 할 때
아래가 전형적인 방법이다.
bool IsA( Class* pA, Class* pB )
{
while( *pA != NULL )
{
if( pA == pB )
{
return true;
}
pA = pA->GetParentClass();
}
}
이렇게 될 경우 운이 나쁘면 비교하는 작업의 시간이 길어질 수 있다.
프로젝트 막바지에 운이 좋게 아래와 같이 정확히 두개씩 자식노드가 분기되는 형태로 되었다고 가정하자.

이름 아이디 클래스색인
Object 1 수준1
Human 2 수준2
Weapon 3 수준3
Warrior 4 수준3
Mage 5 수준3
Sword 6 수준3
Bow 7 수준3
여기서 클래스 색인과 아이디를 이용해 반복문 없이 자식관계를 판정할 수 있다.
판정을 할 때 BitScanReverse 함수를 사용한다. 이 함수는 주어진 값의 비트들에서 제일 왼쪽에 있는 1비트의 위치를 돌려준다.
1 ( 10진수 1 ) -> 0
10 ( 10진수 2 ) -> 1
11 ( 10진수 3 ) -> 1
111 ( 10진수 7 ) -> 2
위의 균형잡힌 트리대로 노드가 구축되어 있다면 비트연산을 통해 부모관계를 판단하기가 쉽다.
위 노드들을 2진수로 표현해 보자.

여기서 BitScanReverse 를 이용해 부모관계를 판단해 보자.
우선 가장 위쪽에 있는 1을 BitScanReverse로 값을 받으면 0 이 나온다.
왼쪽에서 0번째 값이 1인 노드들은 최상위 1의 자식들이다.
그렇다. 여기 그림에 있는 모든 노드는 1의 자식이다. 왼쪽 0번째 값이 1이 아닌 값이 없기 때문이다.
그 다음으로 10으로 보자. 10진수로 2인데 BitScanReverse로 값을 받으면 1 이 나온다.
왼쪽에서 0번째, 1번째 값이 10 이면 10 의 자식이다. 여기서 100, 101 이 자식이 된다.
다음으로 11으로 보자. 10진수로 3인데 BitScanReverse로 값을 받으면 1 이 나온다.
왼쪽에서 0번째, 1번째 값이 11 이면 11의 자식이다. 여기서 110, 111 이 자식이 된다.
아래가 위 내용을 판단하는 코드이다.
bool FastIsA( Class* pA, Class *pB )
{
int nAIndex = pA->GetClassIndex();
int nBIndex = pA->GetClassIndex();
return nBIndex == ( nAIndex >> ( BitScanReverse(nAIndex) - BitScanReverse(nBIndex) );
}
위 경우는 반드시 균현잡힌 트리 구조일 때 사용이 가능하다. 하지만 모든 프로젝트에서 정보를 저렇게 구현한다고는
생각하기 어렵다.
그래서 균형 이진 트리가 아니더라도 허위 노드를 삽입해서 균형 이진트리 비슷한 모양을 구축하면 위 방법대로 사용할 수 있다.
자식노드의 개수와 레벨을 통해 허위 노드를 어떻게 만들지 판단한다.
void BuildTree( Class* pA )
{
int nCurrentClassIndex = pA->GetClassIndex();
int nNumChildClasses = pA->GetNumberOfChildClasses();
int nNumLevels = BSR(nNumChildClasses) + 1;
int nChildIndexStart = nCurrentClassIndex << nNumLevels;
for( int i = 0 ; i < nNumChildClasses ; ++i )
{
class* pChild = pA->GetChildClass( i );
pChild->SetClassIndex( nChildIndexStart + i );
BuildTree(pChild);
}
}
모양은 바꼈지만 위 방식대로 부모관계를 판단할 수 있는 기틀을 마련할 수 있다.

많은 곳에서 IsA를 이렇게 판단하고 있다면 이 방법을 적용해서 제법 속도향상을 기대할 수 있겠다.
요즘은 제너럴 프로그램을 통해 CPU속도를 빠르게 하는 방법에 대해 관심을 가지고 있어서
이러한 내용들을 계속 공부해 보려 한다.
그리고 요즘 게임에서 돈잔치를 벌이는데 있어 유용한 기술의 보조작업을 하고 있다.
알고리즘 적으로 막히는 부분은 다 해결되서 상당히 기쁘다.
그리고 아래는 라이트 셰프트를 어떻게 해서든 적용해 보고싶은 개발자 아버지를 둔 가정의 흔한 식사 모습.

라이트 셰프트도 마저 해야 하는데........







최근 덧글