Programming

루프 내에서 변수를 선언하는 데 오버 헤드가 있습니까?

procodes 2020. 6. 9. 22:40
반응형

루프 내에서 변수를 선언하는 데 오버 헤드가 있습니까? (C ++) [중복]


이 질문에는 이미 답변이 있습니다.

다음과 같이하면 속도 또는 효율성이 떨어질지 궁금합니다.

int i = 0;
while(i < 100)
{
    int var = 4;
    i++;
}

int var백 번 선언합니다 . 있을 것 같지만 확실하지 않습니다. 이것을 대신하는 것이 더 실용적이고 빠를 것입니다 :

int i = 0;
int var;
while(i < 100)
{
    var = 4;
    i++;
}

아니면 속도와 효율성면에서 동일합니까?


지역 변수의 스택 공간은 일반적으로 함수 범위에 할당됩니다. 따라서 루프 내에서 스택 포인터 조정이 발생하지 않고 4를 할당하면 var됩니다. 따라서이 두 스 니펫의 오버 헤드는 동일합니다.


기본 유형 및 POD 유형의 경우 아무런 차이가 없습니다. 컴파일러는 함수 시작시 변수의 스택 공간을 할당하고 함수가 두 경우 모두 반환되면 할당 해제합니다.

사소한 생성자가없는 비 POD 클래스 유형의 경우 차이가 있습니다.이 경우 변수를 루프 외부에두면 생성자와 소멸자를 한 번만 지정하고 할당 연산자는 각 반복을 호출하지만 루프는 루프가 반복 될 때마다 생성자와 소멸자를 호출합니다. 클래스의 생성자, 소멸자 및 할당 연산자의 기능에 따라 바람직하지 않을 수도 있습니다.


그것들은 모두 동일하며, 컴파일러가 무엇을하는지 (최적화를 높게 설정하지 않은 경우에도) 살펴보면 다음과 같이 알 수 있습니다

간단한 예제에서 컴파일러 (gcc 4.0)의 기능을 살펴보십시오.

1.c :

main(){ int var; while(int i < 100) { var = 4; } }

gcc -S 1.c

1.s :

_main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $24, %esp
    movl    $0, -16(%ebp)
    jmp L2
L3:
    movl    $4, -12(%ebp)
L2:
    cmpl    $99, -16(%ebp)
    jle L3
    leave
    ret

2.c

main() { while(int i < 100) { int var = 4; } }

gcc -S 2.c

2.s :

_main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    $0, -16(%ebp)
        jmp     L2
L3:
        movl    $4, -12(%ebp)
L2:
        cmpl    $99, -16(%ebp)
        jle     L3
        leave
        ret

이것들로부터, 당신은 두 가지를 볼 수 있습니다 : 첫째, 코드는 둘 다 동일합니다.

두 번째로 var의 저장소는 루프 외부에 할당됩니다.

         subl    $24, %esp

그리고 마지막으로 루프에서 유일한 것은 할당 및 조건 확인입니다.

L3:
        movl    $4, -12(%ebp)
L2:
        cmpl    $99, -16(%ebp)
        jle     L3

루프를 완전히 제거하지 않고도 가능한 한 효율적입니다.


요즘 컴파일러가 코드를 더 잘 최적화 할 수 있기 때문에 상수가 아닌 한 루프 내에서 선언하는 것이 좋습니다 (변수 범위를 줄임).

편집 :이 답변은 현재 대부분 사용되지 않습니다. 포스트-클래식 컴파일러가 등장하면서 컴파일러가이를 알아낼 수없는 경우는 점점 드물어지고 있습니다. 나는 여전히 그것들을 만들 수 있지만 대부분의 사람들은 건축을 나쁜 코드로 분류합니다.


Most modern compilers will optimize this for you. That being said I would use your first example as I find it more readable.


For a built-in type there will likely be no difference between the 2 styles (probably right down to the generated code).

However, if the variable is a class with a non-trivial constructor/destructor there could well be a major difference in runtime cost. I'd generally scope the variable to inside the loop (to keep the scope as small as possible), but if that turns out to have a perf impact I'd look to moving the class variable outside the loop's scope. However, doing that needs some additional analysis as the semantics of the ode path may change, so this can only be done if the sematics permit it.

An RAII class might need this behavior. For example, a class that manages file access lifetime might need to be created and destroyed on each loop iteration to manage the file access properly.

Suppose you have a LockMgr class that acquires a critical section when it's constructed and releases it when destroyed:

while (i< 100) {
    LockMgr lock( myCriticalSection); // acquires a critical section at start of
                                      //    each loop iteration

    // do stuff...

}   // critical section is released at end of each loop iteration

is quite different from:

LockMgr lock( myCriticalSection);
while (i< 100) {

    // do stuff...

}

Both loops have the same efficiency. They will both take an infinite amount of time :) It may be a good idea to increment i inside the loops.


I once ran some perfomance tests, and to my surprise, found that case 1 was actually faster! I suppose this may be because declaring the variable inside the loop reduces its scope, so it gets free'd earlier. However, that was a long time ago, on a very old compiler. Im sure modern compilers do a better job of optimizing away the diferences, but it still doesn't hurt to keep your variable scope as short as possible.


#include <stdio.h>
int main()
{
    for(int i = 0; i < 10; i++)
    {
        int test;
        if(i == 0)
            test = 100;
        printf("%d\n", test);
    }
}

Code above always prints 100 10 times which means local variable inside loop is only allocated once per each function call.


The only way to be sure is to time them. But the difference, if there is one, will be microscopic, so you will need a mighty big timing loop.

More to the point, the first one is better style because it initializes the variable var, while the other one leaves it uninitialized. This and the guideline that one should define variables as near to their point of use as possible, means that the first form should normally be preferred.


With only two variables, the compiler will likely be assign a register for both. These registers are there anyway, so this doesn't take time. There are 2 register write and one register read instruction in either case.


I think that most answers are missing a major point to consider which is: "Is it clear" and obviously by all the discussion the fact is; no it is not. I'd suggest in most loop code the efficiency is pretty much a non-issue (unless you calculating for a mars lander), so really the only question is what looks more sensible and readable & maintainable - in this case I'd recommend declaring the variable up front & outside the loop - this simply makes it clearer. Then people like you & I would not even bother to waste time checking online to see if it's valid or not.


thats not true there is overhead however its neglect able overhead.

Even though probably they will end up at same place on stack It still assigns it. It will assign memory location on stack for that int and then free it at the end of }. Not in heap free sense in sense it will move sp (stack pointer) by 1. And in your case considering it only has one local variable it will just simply equate fp(frame pointer) and sp

Short answer would be: DONT CARE EITHER WAY WORKS ALMOST THE SAME.

But try reading more on how stack is organized. My undergrad school had pretty good lectures on that If you wanna read more check here http://www.cs.utk.edu/~plank/plank/classes/cs360/360/notes/Assembler1/lecture.html

참고URL : https://stackoverflow.com/questions/982963/is-there-any-overhead-to-declaring-a-variable-within-a-loop-c

반응형