while 루프를 사용하는 것보다 파이썬에서 range ()를 반복하는 것이 왜 더 빠릅니까?
다른 날 파이썬 벤치마킹을하던 중 흥미로운 것을 발견했습니다. 다음은 거의 동일한 작업을 수행하는 두 개의 루프입니다. 루프 1은 실행하는 데 루프 2의 약 두 배가 걸립니다.
루프 1 :
int i = 0
while i < 100000000:
i += 1
루프 2 :
for n in range(0,100000000):
pass
첫 번째 루프가 왜 그렇게 느린가요? 나는 그것이 사소한 예라는 것을 알고 있지만 그것은 내 관심을 불러 일으켰습니다. 같은 방식으로 변수를 증가시키는 것보다 더 효율적으로 만드는 range () 함수에 특별한 것이 있습니까?
파이썬 바이트 코드의 분해를 보면 좀 더 구체적인 아이디어를 얻을 수 있습니다.
while 루프 사용 :
1 0 LOAD_CONST 0 (0)
3 STORE_NAME 0 (i)
2 6 SETUP_LOOP 28 (to 37)
>> 9 LOAD_NAME 0 (i) # <-
12 LOAD_CONST 1 (100000000) # <-
15 COMPARE_OP 0 (<) # <-
18 JUMP_IF_FALSE 14 (to 35) # <-
21 POP_TOP # <-
3 22 LOAD_NAME 0 (i) # <-
25 LOAD_CONST 2 (1) # <-
28 INPLACE_ADD # <-
29 STORE_NAME 0 (i) # <-
32 JUMP_ABSOLUTE 9 # <-
>> 35 POP_TOP
36 POP_BLOCK
루프 본체에는 10 개의 op가 있습니다.
사용 범위 :
1 0 SETUP_LOOP 23 (to 26)
3 LOAD_NAME 0 (range)
6 LOAD_CONST 0 (0)
9 LOAD_CONST 1 (100000000)
12 CALL_FUNCTION 2
15 GET_ITER
>> 16 FOR_ITER 6 (to 25) # <-
19 STORE_NAME 1 (n) # <-
2 22 JUMP_ABSOLUTE 16 # <-
>> 25 POP_BLOCK
>> 26 LOAD_CONST 2 (None)
29 RETURN_VALUE
루프 본문에는 3 개의 작업이 있습니다.
C 코드를 실행하는 시간은 정수기보다 훨씬 짧으며 무시할 수 있습니다.
range()C로 구현되지만 i += 1해석됩니다.
사용하면 xrange()많은 수의 경우 더 빨리 만들 수 있습니다. Python 3.0부터는 range()이전과 동일합니다 xrange().
while 루프에서 많은 객체 생성 및 파괴가 진행되고 있다고 말해야합니다.
i += 1
와 같다:
i = i + 1
그러나 Python int는 변경 불가능하기 때문에 기존 객체를 수정하지 않습니다. 오히려 그것은 새로운 가치를 가진 새로운 물건을 창조합니다. 기본적으로 다음과 같습니다.
i = new int(i + 1) # Using C++ or Java-ish syntax
가비지 수집기는 또한 많은 양의 정리 작업을 수행해야합니다. "객체 생성은 비싸다".
인터프리터에서 C로 작성된 코드로 더 자주 실행되기 때문입니다. 즉, i + = 1은 Python에 있으므로 (비교적으로) 느리지 만 range (0, ...)은 하나의 C 호출이며 for 루프는 대부분 C에서도 실행됩니다.
Most of Python's built in method calls are run as C code. Code that has to be interpreted is much slower. In terms of memory efficiency and execution speed the difference is gigantic. The python internals have been optimized to the extreme, and it's best to take advantage of those optimizations.
'program story' 카테고리의 다른 글
| 전역 변수가 나쁘다고 들었습니다. 어떤 대체 솔루션을 사용해야합니까? (0) | 2020.10.31 |
|---|---|
| 텍스트가 일관성없이 렌더링되고 일부 글꼴이 다른 글꼴보다 큰 모바일 Safari (iPhone)의 글꼴 크기 문제를 해결합니까? (0) | 2020.10.31 |
| 날짜가 yyyy-dd-MM 형식 인 DateTime.TryParse 문제 (0) | 2020.10.31 |
| Elasticsearch 2.0에서 원격 액세스 / 요청을 활성화하려면 어떻게해야합니까? (0) | 2020.10.31 |
| 쉘 스크립트에서 기간을 초 단위로 측정하려면 어떻게합니까? (0) | 2020.10.31 |