최대가 정렬보다 느린 이유는 무엇입니까?


92

나는 그것이 파이썬 2와 3 maxsort함수 보다 느리다 는 것을 발견했습니다 .

파이썬 2

$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 239 usec per loop
$ python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'max(a)'        
1000 loops, best of 3: 342 usec per loop

파이썬 3

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a.sort();a[-1]'
1000 loops, best of 3: 252 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a)'
1000 loops, best of 3: 371 usec per loop

( )이 함수 ( ) 보다 느린 이유 무엇 입니까?maxO(n)sortO(nlogn)


3
Python 2 분석을 한 번 실행했는데 Python 3 코드가 정확히 동일합니다.
erip

9
a.sort()제자리에서 작동합니다. 시도sorted(a)
안드레아 Corbellini에게

문제를 해결했다면 문제를 해결하기 위해 무엇을했는지 다시 게시 해주세요.
Pretzel

4
@Pretzel OP는 문제가 수정 된 것이 아니라 게시물이 수정되었음을 의미합니다.
erip

2
@WeizhongTu하지만 sort다음 종류의, 그리고 a영원히 정렬
njzk2

답변:


125

timeit파이썬 에서 모듈을 사용할 때 매우 조심해야합니다 .

python -m timeit -s 'import random;a=range(10000);random.shuffle(a)' 'a.sort();a[-1]'

여기서 초기화 코드는 무작위 배열을 생성하기 위해 한 번 실행됩니다. a . 그런 다음 나머지 코드가 여러 번 실행됩니다. 처음에는 배열을 정렬하지만 다른 때마다 이미 정렬 된 배열에서 정렬 메서드를 호출합니다. 가장 빠른 시간 만 반환되므로 Python이 이미 정렬 된 배열을 정렬하는 데 걸리는 시간을 실제로 측정합니다.

파이썬의 정렬 알고리즘의 일부는 배열이 이미 부분적으로 또는 완전히 정렬되었는지 감지하는 것입니다. 완전히 정렬되면이를 감지하기 위해 어레이를 한 번만 스캔 한 다음 중지합니다.

대신 시도한 경우 :

python -m timeit -s 'import random;a=range(100000);random.shuffle(a)' 'sorted(a)[-1]'

그런 다음 정렬은 모든 타이밍 루프에서 발생하며 배열을 정렬하는 데 걸리는 시간이 단순히 최대 값을 찾는 것보다 훨씬 길다는 것을 알 수 있습니다.

편집 : @skyking의 대답 은 내가 설명하지 않은 부분을 설명합니다 a.sort(). 목록에서 작업 중이므로 요소에 직접 액세스 할 수 있습니다. max(a)임의의 이터 러블에서 작동하므로 일반 이터 레이션을 사용해야합니다.


10
잘 잡았습니다. 인터프리터 상태가 코드 실행 동안 유지된다는 것을 결코 깨달았습니다. 이제 나는 과거에 얼마나 많은 잘못된 벤치 마크를 만들 었는지 궁금합니다. :-}
Frerich Raabe

1
저에게는 그 정도가 분명했습니다. 그러나 이미 정렬 된 배열을 정렬하더라도 모든 요소를 ​​확인해야합니다. 그것은 최대를 얻는 것만큼이나 많은 일입니다 .... 나에게 이것은 절반의 대답처럼 보입니다.
Karoly Horvath

2
@KarolyHorvath, 당신이 맞습니다. @skyking이 답의 나머지 절반을 얻었다 고 생각 a.sort()합니다. 목록에서 작업 중이므로 요소에 직접 액세스 할 수 있습니다. max(a)일반 반복을 사용하지 않도록 임의의 시퀀스에서 작동합니다.
Duncan

1
@KarolyHorvath 어쩌면 분기 예측은 왜 반복적으로 정렬 된 배열을 정렬 설명 할 수있는 것은 빠르다 : stackoverflow.com/a/11227902/4600
marcospereira

1
@JuniorCompressor listsort.txt는 "많은 종류의 부분적으로 정렬 된 배열에서 초자연적 인 성능을 제공합니다 (LG (N!) 비교가 필요하지 않고 N-1만큼 적음)"라고 설명하고 계속해서 모든 종류의 최적화를 설명합니다. 나는 그것이 max불가능한 많은 가정을 할 수 있다고 생각합니다 . 즉, 정렬이 점근 적으로 더 빠르지 않습니다.
Frerich Raabe

87

먼저 max()반복자 프로토콜사용하고 list.sort()임시 코드사용합니다 . 분명히 반복자를 사용하는 것은 중요한 오버 헤드이므로 타이밍의 차이를 관찰하는 것입니다.

그러나 그 외에는 테스트가 공정하지 않습니다. a.sort()동일한 목록에서 두 번 이상 실행 중 입니다. 파이썬 사용 알고리즘 특히 빠른 이미 용으로 설계된다 (부분적) 데이터를 분류. 테스트에 따르면 알고리즘이 제대로 작동하고 있습니다.

다음은 공정한 테스트입니다.

$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'max(a[:])'
1000 loops, best of 3: 227 usec per loop
$ python3 -m timeit -s 'import random;a=list(range(10000));random.shuffle(a)' 'a[:].sort()'
100 loops, best of 3: 2.28 msec per loop

여기에서는 매번 목록의 복사본을 만듭니다. 보시다시피 결과의 크기는 우리가 예상하는대로 마이크로 초와 밀리 초로 다릅니다.

그리고 기억하세요 : big-Oh는 상한을 지정합니다! 파이썬 정렬 알고리즘의 하한은 Ω ( n )입니다. O ( n log n )이된다고해서 모든 실행이 n log n에 비례하는 시간이 걸린다는 것을 자동으로 의미하지는 않습니다 . 그것은 O ( n ) 알고리즘 보다 느려 야한다는 것을 의미조차하지 않지만 그것은 또 다른 이야기입니다. 이해해야 할 중요한 것은 일부 유리한 경우 O ( n log n ) 알고리즘이 O ( n ) 시간 이하로 실행될 수 있다는 것 입니다.


31

이는 while l.sort의 멤버 가 일반 함수 이기 때문일 수 있습니다 . 이것은 while 의 내부 표현에 의존 할 수 있다는 것을 의미 하며 일반 반복기 프로토콜을 거쳐야합니다.listmaxl.sortlistmax

이것은 각 요소 가져 오기가 수행하는 각 요소 가져 오기 l.sort보다 빠릅니다 max.

대신 사용 sorted(a)하면 결과가 max(a).


5
그 가정은 좀 더 구체적이되기까지 한 줄의 시간 일뿐입니다. 당신의 지식에 의문을 제기하지 않고, 그러한 추가는 그것을 모르는 사람들의 시연에 사소한 것입니다.
Reti43

sorted(a)보다 느린 것이 맞습니다 max(a). 당연히 그것은와 거의 같은 속도 a.sort()이지만 그렇지 않은 이유에 대한 귀하의 추측입니다. OP가 허용 된 답변에서 지적한대로 테스트에서 실수를했기 때문입니다.
martineau

요점은 일반 반복기 프로토콜이 log(n)복잡성 요소 를 상쇄하기에 충분한 오버 헤드를 가질 가능성이 있다는 것입니다 . 즉, O(n)알고리즘은 O(nlogn)충분히 큰 알고리즘 보다 빠르다는 것이 보장됩니다 n(예를 들어 각 작업에 대한 시간이 알고리즘마다 다를 nlogn수 있으므로 빠른 단계가 n느린 단계 보다 빠를 수 있음 ). 이 경우 손익분기 점이 정확히 어디에 있는지는 고려되지 않았습니다 (그러나 log n작은 요소에 대해서는 그 요소가 그다지 큰 요소가 아님을 알아야합니다 n).
skyking
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.