2011-10-11 4 views
2

필자는 컴파일러가 기능 및 변수 호출을 본질적으로 코드로 대체하여 교묘하게 대체한다는 사실을 알게되었습니다. 이 점을 염두에 두 번째 방법은 사실 아래 (선명도 때문에)보다 좋으며 실제로 첫 번째 방법만큼 빠르게 실행됩니까?컴파일러 최적화

//check to see if sphere intersects the box 
bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
// check for intersection on each axis by seeing if the radius is large enough to reach the edge of the cube on the 
// appropriate side. All must evaluate to true for there to be an intersection. 
return (
    ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
    (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x)) 
    && 
    ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
    (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y)) 
    && 
    ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
    (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z))); 
} 

두 번째 방법 : 당신의 예상되는 동작의 보장이 없습니다

//check to see if sphere intersects the box 
bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
bool xIntersects, yIntersect, zIntersects; 

xIntersects = 
    ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
    (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x))); 

yIntersects = 
      ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
    (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y))); 

zIntersects = 
      ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
    (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z))); 

return (xIntersects && yIntersects && zIntersects); 
} 
+0

아마 둘 다 상대적으로 비슷하지만 두 번째 것은 더 명확하지만 더 많은 선을 사용한다는 점에서 가장 좋은 예는 아닙니다. – SirYakalot

+1

어느 정도 그것은 당신이 사용하고있는 컴파일러와 코드를 얼마나 잘 최적화 하느냐에 달려 있습니다. – Eilidh

+3

이것은 가독성과 최적화에 관한 것입니다. – Philip

답변

1

우선, 이것은 정확한 구 대 상자 수표가 아닙니다. 본질적으로 깨진 것입니다 (구면 중심이 박스에 포함되어있을 때 교차로를보고하지 않습니다!) box 대 box-around-a-sphere 테스트. 이 작업을 올바르게 수행하려면 Arvo의 알고리즘을 찾으십시오.

그러나 질문에 대한 답 : 측정 가능한 속도 차이가 있고 거기에 의심의 여지가 있다면 가장 확실하게 인라이닝과 관련이 없지만 두 기능의 약간 다른 의미에 관련됩니다. 첫 번째 함수는 && 연산자를 통해 최상위 레벨에서 지연 평가를 수행합니다. 따라서 첫 번째 축에서 음의 결과를 얻으면 다른 축척을 테스트하지 않고 튀어 나옵니다. 이 축 또는 두 번째 축에 부정적 결과가 충분할 경우 매우 느린 컴퓨터에서 속도 이점을 얻을 수 있습니다.

두 번째 기능은 이전 축에서 음수 응답이 있는지 여부를 확인하지 않습니다. 결과적으로, 그것은 항상 세 가지 모두를 테스트 할 것입니다. 이제는 괜찮은 컴퓨터에서 더 빠를 것입니다. 첫 번째 검사 결과가 다음에 오는 검사를 실행할 수 있는지 여부를 파악할 때까지 기다릴 필요가 없기 때문입니다. 따라서 일반적으로 분기 예측 오류가 적기 때문에 두 분기의 작업을 수행하는 것보다 빠릅니다.

그런 다음 옵티마이 저가 부작용없이 && 연산자의 반대쪽에서 표현식을 실행할 수 있다는 것을 알기에 충분히 똑똑 할 수도 있습니다. 옵티마이 저가 CentreRadius 함수가 실제로 무엇을하는지 알아야하기 때문에 인라인 (명시 적으로 또는 링크 타임 코드 생성을 통해)이 실제로 작은 역할을 수행합니다.

하지만 알고있는 유일한 방법은 생성 된 코드를보고 벤치마킹하는 것입니다.

+0

나를 arvo 방향으로 가르쳐 주셔서 감사합니다. – SirYakalot

8

- 컴파일러는 그것을위한 모든 조건을 계산하지 않았다 해결 꽤 현명 할 것이 x/y/z를 반환합니다.

첫 번째 버전에서는 처음 실패한 테스트로 돌아갑니다. 나는 그것에 충실 할 것이고, 주석을 만들고 코드를 명확하게 포맷 할 것이다.

+0

동의합니다. 슬프게도, 나는 투표에서 뺄 수있다. –

1

나는이 둘의 조합을 주장 할 것이다. xIntersects && yIntersects && z Intersects을 확인하려면 각자 고유 한 기능을 수행하십시오. 그래서 같이 :

bool BoundingBox::Intersects(BoundingSphere boundingSphere) 
{ 
    return XIntersects(boundingSphere) && YIntersects(boundingSphere) && ZIntersects(boundingSphere); 
} 

bool BoundingBox::XIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().x < negCorner.x && boundingSphere.Radius() > posCorner.x - boundingSphere.Centre().x) || 
      (boundingSphere.Centre().x > posCorner.x && boundingSphere.Radius() > boundingSphere.Centre().x - negCorner.x)); 
} 
bool BoundingBox::YIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().y < negCorner.y && boundingSphere.Radius() > posCorner.y - boundingSphere.Centre().y) || 
      (boundingSphere.Centre().y > posCorner.y && boundingSphere.Radius() > boundingSphere.Centre().y - negCorner.y)); 
} 
bool BoundingBox::ZIntersects(BoundingSphere boundingSphere) 
{ 
    return ((boundingSphere.Centre().z < negCorner.z && boundingSphere.Radius() > posCorner.z - boundingSphere.Centre().z) || 
      (boundingSphere.Centre().z > posCorner.z && boundingSphere.Radius() > boundingSphere.Centre().z - negCorner.z)); 
} 

당신은 함수 호출을 최적화 할 수있는 최초의 속도와 두 번째의 선명도 및 최적화 컴파일러 모두를 얻을.

관련 문제