[c++] <보다 빠르고 <=입니까?



Answers

역사적으로 (우리는 1980 년대와 1990 년대 초반을 이야기했습니다), 이것이 사실이었던 몇 가지 아키텍처가있었습니다. 근본적인 문제는 정수 비교가 본질적으로 정수 빼기를 통해 구현된다는 것입니다. 이로 인해 다음과 같은 경우가 발생합니다.

Comparison     Subtraction
----------     -----------
A < B      --> A - B < 0
A = B      --> A - B = 0
A > B      --> A - B > 0

이제, A < B 일 때, 빼기가 정확하도록 뺄셈은 높은 비트를 빌려야합니다. 손으로 더하거나 뺄 때와 마찬가지입니다. 이 "빌린"비트는 일반적으로 캐리 비트 (carry bit) 라고하며 분기 명령에 의해 테스트 할 수 있습니다. 뺄셈이 동등 함을 의미하는 0 인 경우 0 비트라고하는 두 번째 비트가 설정됩니다.

일반적으로 적어도 두 개의 조건부 분기 명령어가 있었는데, 하나는 캐리 비트에서 분기하고 다른 하나는 제로 비트에서 분기하는 것입니다.

이제는 문제의 핵심에 도달하기 위해 이전 표를 확장하여 올림 및 제로 비트 결과를 포함 시키십시오.

Comparison     Subtraction  Carry Bit  Zero Bit
----------     -----------  ---------  --------
A < B      --> A - B < 0    0          0
A = B      --> A - B = 0    1          1
A > B      --> A - B > 0    1          0

따라서 A < B 대한 분기를 구현하는 것은 하나의 명령어로 수행 될 수 있습니다.이 경우 carry 비트가 지워지기 때문입니다. 즉,

;; Implementation of "if (A < B) goto address;"
cmp  A, B          ;; compare A to B
bcz  address       ;; Branch if Carry is Zero to the new address

그러나 우리가 덜 - 또는 - 동등한 비교를하고 싶다면, 우리는 평등의 경우를 잡기 위해 제로 플래그에 대한 추가적인 점검을 할 필요가있다.

;; Implementation of "if (A <= B) goto address;"
cmp A, B           ;; compare A to B
bcz address        ;; branch if A < B
bzs address        ;; also, Branch if the Zero bit is Set

따라서 일부 시스템에서는 "미만"비교를 사용하면 하나의 기계 명령어를 절약 할 수 있습니다 . 이것은 서브 메가 헤르츠 프로세서 속도와 1 : 1 CPU 대 메모리 속도 비율의 시대와 관련이 있었지만 오늘날에는 거의 무의미합니다.

Question

저자 if( a < 901 )if( a <= 900 ) 보다 빠르다고 말하는 저자의 책을 읽었습니다.

이 간단한 예제와 똑같은 것은 아니지만 루프 복잡한 코드에서 약간의 성능 변화가 있습니다. 이것이 사실이라면 생성 된 기계 코드로 무언가를해야한다고 생각합니다.




어느 쪽도 빠르지 않다. 컴파일러는 각 조건에서 다른 값을 가진 동일한 컴퓨터 코드를 생성합니다.

if(a < 901)
cmpl  $900, -4(%rbp)
jg .L2

if(a <=901)
cmpl  $901, -4(%rbp)
jg .L3

내 예제는 리눅스에서 x86_64 플랫폼의 GCC에서 온 if 입니다.

컴파일러 작성자는 꽤 똑똑한 사람들이며, 우리 대부분이 당연한 것으로 생각합니다.

나는 상수가 아니라면 동일한 기계 코드가 생성되는 것을 발견했다.

int b;
if(a < b)
cmpl  -4(%rbp), %eax
jge   .L2

if(a <=b)
cmpl  -4(%rbp), %eax
jg .L3



여분의 문자로 인해 코드 처리가 약간 느려지므로 대부분의 스크립팅 언어에서 해당 줄이 정확하다고 말할 수 있습니다. 그러나 최상위 답변이 지적한대로 C ++에는 효과가 없어야하며 스크립팅 언어로 수행되는 작업은 최적화에 관심이없는 것 같습니다.




그들은 같은 속도를 가지고 있습니다. 어쩌면 일부 특수 아키텍처에서 그 / 그녀가 말한 바는 맞지만 x86 패밀리에서는 적어도 동일하다고 알고 있습니다. 이렇게하기 위해 CPU는 빼기 (a - b)를 수행 한 다음 플래그 레지스터의 플래그를 확인합니다. 이 레지스터의 두 비트는 ZF (제로 플래그) 및 SF (부호 플래그)라고하며, 하나의 마스크 연산으로 수행하기 때문에 한 사이클로 완료됩니다.




어쩌면 그 이름없는 책의 저자는 a > 0a >= 1 보다 빨리 달리고 그것이 보편적으로 진실이라고 생각합니다.

하지만 0 이 관련되어 있기 때문입니다 ( CMP 가 아키텍처에 따라 예를 들어 OR 로 대체 될 수 있기 때문에).




다른 대답은 x86 아키텍처에 집중되어 있으며, 생성 된 코드에 대해 특별히 언급할만한 ARM 아키텍처 (예제 어셈블러 인 것 같습니다)는 모르지만, 이것은 매우 micro-optimisationmicro-optimisation 의 예입니다 특정 적이며, 최적화가 아닌 반 최적화될 가능성이 큽니다 .

따라서, 나는 이런 종류의 micro-optimisation 가 최상의 소프트웨어 공학 실습 이라기보다는 화물 컬트 프로그래밍의 예라고 제안 할 것이다.

아마도 이것이 최적화 인 아키텍처가 있을지도 모르겠지만 그 반대가 사실 일 수있는 적어도 하나의 아키텍처를 알고 있습니다. 훌륭한 Transputer 아키텍처는 거나 더 크거나 같은 머신 코드 명령어만을 가지고 있었기 때문에 이러한 모든 프리미티브를 모든 비교 작업에 적용해야했습니다.

심지어 거의 모든 경우에, 컴파일러는 실제적으로 비교가 다른 어떤 것보다 이점을 갖지 않는 방식으로 평가 지시를 주문할 수 있습니다. 최악의 경우지만, 피연산자 스택 의 상위 두 항목을 바꾸려면 역방향 명령 (REV)을 추가해야 할 수도 있습니다. 이것은 단일 사이클을 실행하는 단일 바이트 명령 이었으므로 가능한 가장 작은 오버 헤드가있었습니다.

이와 같은 미세 최적화가 최적화 또는 최적화 가 아닌지 여부는 사용중인 특정 아키텍처에 따라 다르므로 아키텍처 별 미세 최적화를 사용하는 습관을 갖지 않는 것이 좋습니다. 그렇지 않으면 본능적으로 그것을하는 것이 부적당 할 때 그것을 사용 하거든, 당신이 읽고있는 책이 옹호하고있는 무슨 정확하게 인처럼 본다.




Related