programing

"iff" 대 "if other if"의 성능 차이

powerit 2023. 9. 15. 21:24
반응형

"iff" 대 "if other if"의 성능 차이

C/C++의 두 문장 사이에 성능 차이가 있는지 생각하고 있었습니다.

사례 1:

if (p==0)
   do_this();
else if (p==1)
   do_that();
else if (p==2)
   do_these():

사례 2:

if(p==0)
    do_this();
if(p==1)
    do_that();
if(p==2)
    do_these();

단순한 유형을 가정할 때(이 경우 사용했습니다.int) 및 재미있는 비즈니스는 없습니다(operator= forint를 재정의하지 않음). 적어도 AMD64의 GCC 4.6에서는 차이가 없습니다.생성된 코드는 동일합니다.

0000000000000000 <case_1>:                                   0000000000000040 <case_2>:
   0:   85 ff                   test   %edi,%edi               40:   85 ff                   test   %edi,%edi
   2:   74 14                   je     18 <case_1+0x18>        42:   74 14                   je     58 <case_2+0x18>
   4:   83 ff 01                cmp    $0x1,%edi               44:   83 ff 01                cmp    $0x1,%edi
   7:   74 27                   je     30 <case_1+0x30>        47:   74 27                   je     70 <case_2+0x30>
   9:   83 ff 02                cmp    $0x2,%edi               49:   83 ff 02                cmp    $0x2,%edi
   c:   74 12                   je     20 <case_1+0x20>        4c:   74 12                   je     60 <case_2+0x20>
   e:   66 90                   xchg   %ax,%ax                 4e:   66 90                   xchg   %ax,%ax
  10:   f3 c3                   repz retq                      50:   f3 c3                   repz retq 
  12:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)        52:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  18:   31 c0                   xor    %eax,%eax               58:   31 c0                   xor    %eax,%eax
  1a:   e9 00 00 00 00          jmpq   1f <case_1+0x1f>        5a:   e9 00 00 00 00          jmpq   5f <case_2+0x1f>
  1f:   90                      nop                            5f:   90                      nop
  20:   31 c0                   xor    %eax,%eax               60:   31 c0                   xor    %eax,%eax
  22:   e9 00 00 00 00          jmpq   27 <case_1+0x27>        62:   e9 00 00 00 00          jmpq   67 <case_2+0x27>
  27:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)        67:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  2e:   00 00                                                  6e:   00 00 
  30:   31 c0                   xor    %eax,%eax               70:   31 c0                   xor    %eax,%eax
  32:   e9 00 00 00 00          jmpq   37 <case_1+0x37>        72:   e9 00 00 00 00          jmpq   77 <case_2+0x37>
  37:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  3e:   00 00 

case_1의 끝에 있는 추가 명령어는 (다음 함수를 정렬하기 위해) 패딩을 위한 것입니다.

이 함수에서 p가 변하지 않는다는 것을 파악하는 것은 상당히 기본적인 최적화입니다.p를 변경할 수 있는 경우(예: pass-by-reference 또는 pointer to various)do_…함수, 또는 참조 또는 포인터 자체였으므로 별칭이 있을 수 있습니다). 그러면 동작이 다르며, 물론 생성된 코드도 마찬가지입니다.

전자의 경우 일치된 조건 이후의 조건은 평가되지 않습니다.

다른 경우에는 빠릅니다. 일치하는 항목이 마지막에 발견된 경우에는 최소한 마지막에 발견된 경우에는 문을 건너뛰고, 일치하는 경우에는 일치하는 항목이 처음에 발견된 경우에는 다른 모든 문을 건너뜁니다.

if가 느릴 경우, first if 문을 사용하여 일치가 발견되더라도 다른 문에서 일치를 계속 시도합니다.

예, 성능 차이는 다음과 같습니다.

두 번째 문장은 모든 IF를 평가합니다.

이미 입증되었듯이...다양합니다.

만약 우리가 원시적인 (빌트인) 유형에 대해 이야기한다면 다음과 같습니다.int, 그러면 컴파일러는 문제가 되지 않을 정도로 충분히 똑똑할 수 있습니다.그러나 어떤 경우에도, 함수를 호출하는 비용이 a보다 훨씬 높기 때문에 성능에 미치는 영향은 미미할 것입니다.if, 측정을 시도하면 소음 속에서 차이가 날 수 있습니다.

그러나 의미론은 상당히 다릅니다.

첫 번째 사례를 읽었을 때:

if (...) {
  // Branch 1
} else if (...) {
  // Branch 2
}

그렇다면 두 갈래가 어떻게 하든 한 갈래만 실행할 수 있다는 것을 알고 있습니다.

하지만 두번째 케이스를 읽었을때는

if (...) {
}
if (...) {
}

그러면 두 갈래 모두 취해질 가능성이 있는지, 그렇지 않은지, 두 번째 시험에 영향을 미칠 가능성이 있는지를 판단하기 위해 첫 번째에 코드를 꼼꼼히 살펴봐야 한다는 의미입니다.그리고 내가 마침내 아니라고 결론을 내렸을 때, 나는 그 망할 놈의 글을 쓰기엔 너무 게을렀던 빌어먹을 개발자를 저주합니다.else지난 10분간의 정밀 조사 시간을 아낄 수 있었을 겁니다

그러니 자신과 미래의 유지 관리자들을 돕고, 의미론을 정확하고 명확하게 하는 데 집중하세요.

이, 이 에 은 가 과 될 할 할 될 은 switch도a.map<int, void()>을 피함 고잉를함e;)함를( ; )

이처럼 제한된 수의 표현에 대한 성능 차이는 아마 발견되지 않을 것입니다.으로는.if..if..if모든 식을 확인해야 합니다.배타적인 일이우을여를할수다호인수다gynlfesuse,tny호ee인를if..else if.. 을 확인할.앞의 사례가 실패했을 때만 다른 식을 확인할 수 있습니다.

는 을 int 를 할 은 할 할 을 은 switch 하면할 수 .이렇게 하면 긴 검사 순서 동안에도 가독성을 어느 정도 유지할 수 있습니다.

switch ( p )
{
    case 0:
        do_this();
        break;

    case 1:
        do_that();
        break;

    case 2:
        do_these():
        break;
}

if..실제 논리는 좌-우로 평가되므로 이후의 모든 IF 검사에서 DONE 플래그를 사용하여 이중 작업/일치 및 최적화를 방지함으로써 사례를 개선할 수 있는 경우.

bool bDone = false;

If( <condition> ) {
    <work>;
    bDone = true;
}
if (!bDone && <condition> ) {
    <work>;
    bDone = true;
}

아니면 다음과 같은 논리를 사용할 수도 있습니다.

While(true) {
    if( <condition> ) {
        <work>;
        break;
    }
    if( <condition> ) {
        <work>;
        break;
    }
    ....
    break;
}

읽기에는 다소 혼란스럽지만 ("왜 이런 식으로"라고 묻습니다)

주요 차이점은 if/else 구성이 if() 중 하나가 참을 반환하면 평가를 중지한다는 것입니다.즉, 보석하기 전에 if 중 1개 또는 2개만 실행할 수 있습니다.다른 버전은 다른 버전의 결과에 관계없이 3가지의 모든 if를 확인합니다.

그럼.. 만약.. "최대 3번의 점검"의 운영 비용이 있다면요.if/if/if 버전의 운영 비용은 "항상 3개 확인"입니다.검사 중인 3개의 값이 모두 동일한 가능성이 있다고 가정하면 if/else 버전은 평균 1.5개의 if를 수행하는 반면 if/if 버전은 항상 3개의 if를 수행합니다.장기적으로는 "다른" 컨스트럭트를 사용하면 1.5 ifs의 CPU 시간을 절약할 수 있습니다.

언급URL : https://stackoverflow.com/questions/7970275/performance-difference-of-if-if-vs-if-else-if

반응형