6 ^ 6 ^ 6 평가에서 python vs bc


29

내가 표현하고 평가하는 6^6^6사용 pythonbc별도로합니다.

파이썬 파일의 내용은입니다 print 6**6**6. 내가 실행할 때 time python test.py출력을 다음과 같이 얻습니다.

real        0m0.067s
user        0m0.050s
sys         0m0.011s

그런 다음 명령 time echo 6^6^6 | bc을 실행 하여 다음과 같은 결과를 얻었습니다.

real        0m0.205s
user        0m0.197s
sys         0m0.005s

이 결과로부터 python과 bc에 걸린 sys 시간은 각각 11ms와 5ms임을 알 수 있습니다. bc 명령은 SYS 시간 수준에서 파이썬을 상회 하지만이에 관해서는 사용자와 실시간으로 파이썬 거의 4 배 빠른 기원전 이상이었다 . 거기에 갔을지도 모른다. 나는 프로세스에 우선 순위를 부여하지 않았습니다. 이 상황을 이해하려고합니다.


따라서 sys 구성 요소는로드하는 데 시간이 걸리고 런타임은 출력의 사용자 구성 요소에 제공된다는 것을 의미합니까?
ganessh

나는 확실하지 않다. 그래서 내가 의견을 게시했다. 그냥 추측입니다.
terdon

7
echo | bc파이프 때문에 서브 쉘을 시작하는 것이 포함됩니다. 이것을 평등 한 테스트로 만들기 위해 파이썬 스크립트는 stdin에서 읽어야합니다 time echo 6**6**6 | whatever.py.
goldilocks

1
오히려 be 명령 줄을 스크립트에 넣고 실행 시간을 정하고 싶습니다. 또는을 사용하십시오 echo 6^6^6 | time bc.
다니엘 쿨만

1
참고 사항 : 파이썬에서는 6**6**6표현식이 실제로 컴파일 타임에 계산 됩니다 . 그러나 모듈에서 파일을 가져 오는 대신 파일을 직접 시작하기 때문에 문제가되지 않습니다. 차이 넣어 보려면 10**12345678a.py파일을 대화 형 인터프리터에서 가져보십시오. 그런 다음 인터프리터를 닫고 다시 시작한 후 다시 가져 오십시오 a. 그것은 부하 번째 시간 동안 (파이썬 모듈을 컴파일되므로)는 시간의 양을 띄는 취해야 처음 .pyc순간되어야,
Bakuriu

답변:


25

Python은 시작할 때 많은 파일을 가져옵니다.

% python -c 'import sys; print len(sys.modules)'
39

모듈을 정의하는 방법은 여러 가지가 있기 때문에 각각의 파이썬 파일을 열 때 훨씬 더 많은 시도가 필요합니다.

% python -vv -c 'pass'
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# trying site.so
# trying sitemodule.so
# trying site.py
# trying site.pyc
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/sitemodule.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.py
# /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.pyc matches /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.py
import site # precompiled from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site.pyc
# trying os.so
# trying osmodule.so
# trying os.py
# trying os.pyc
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/osmodule.so
# trying /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py
# /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc matches /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.py
import os # precompiled from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc
    ...

내장 된 것을 제외한 각 "시도"는 os 레벨 / 시스템 호출을 필요로하며, 각각의 "가져 오기"는 약 8 개의 "시도"메시지를 트리거하는 것으로 보입니다. zipimport를 사용하여이를 줄일 수있는 방법이 있으며 PYTHONPATH의 각 경로에 다른 호출이 필요할 수 있습니다.

이것은 파이썬이 내 컴퓨터에서 시작하기 전에 거의 200 개의 통계 시스템 호출이 있고 "시간"은 사용자 프로그램이 시스템에서 작업을 수행하기 때문에 "사용자"가 아닌 "시스템"에 할당한다는 것을 의미합니다.

이에 비해 terdon이 말했듯이 "bc"는 높은 시작 비용이 없습니다. dtruss 출력 (Linux 기반 OS의 경우 Mac; "strace")을 보면 bc가 몇 가지 공유를로드하는 것을 제외하고는 자체적으로 open () 또는 stat () 시스템 호출을하지 않습니다. 라이브러리는 시작이며 물론 파이썬도 마찬가지입니다. 또한 파이썬은 처리 할 준비가되기 전에 읽을 파일이 더 있습니다.

디스크 대기 속도가 느립니다.

다음을 수행하여 Python의 시작 비용을 이해할 수 있습니다.

time python -c pass

내 컴퓨터에서 0.032s이고 'print 6 ** 6 ** 6'은 0.072s이므로 시작 비용은 전체 시간의 1/2이며 계산 + 십진수로의 변환은 절반입니다. 동안:

time echo 1 | bc

0.005 초가 걸리고 "6 ^ 6 ^ 6"은 0.184 초가 걸리므로 시작하는 데 7 배 빠르지 만 bc의 지수는 Python보다 4 배 이상 느립니다.


4
거기에 납을 묻었 어 끝 비트를 맨 위로 이동시킬 수 있습니다.
Riking

그냥 내 컴퓨터에 관심에서 시간 : 파이썬 -c 0m0.025s을 '통과', 시간이 파이썬 -c '6 인쇄 6 파이썬 -c'X = 6 0m0.087s하지만 시간 6 ' 6 그래서 6'0m0.028s을 대부분 의 시간은 많은 수를 출력하고 있습니다.
Steve Barnes

그렇습니다. 10 진법으로의 변환은 자릿수로 2 차 시간이 걸립니다. 극단적 인 경우, 더 큰 메르 센 프라임 중 하나를 인쇄 해보십시오. 그것은 계산에 매우 빠르게,하지만 기본 (10)에 인쇄하는 데 시간이 오래 걸립니다
앤드류 Dalke

11

다른 분야를 설명하는 SO에 대한 좋은 대답 을 찾았습니다 .

  • 통화는 시작부터 끝까지의 시간입니다. 다른 프로세스에서 사용하는 시간 조각과 프로세스가 차단 된 시간을 포함하여 모두 경과 된 시간입니다 (예 : I / O가 완료되기를 기다리는 경우).

  • User는 프로세스 내에서 사용자 모드 코드 (커널 외부)에 소비 된 CPU 시간입니다. 이것은 프로세스 실행에 사용 된 실제 CPU 시간입니다. 프로세스가 차단 한 다른 프로세스와 시간은이 수치에 포함되지 않습니다.

  • Sys는 프로세스 내 커널에서 소비 한 CPU 시간입니다. 이것은 여전히 ​​사용자 공간에서 실행되는 라이브러리 코드와 달리 커널 내에서 시스템 호출에 소비 된 CPU 시간을 실행하는 것을 의미합니다. 'user'와 마찬가지로 프로세스에서 사용하는 CPU 시간입니다. 커널 모드 ( '감독자'모드라고도 함) 및 시스템 호출 메커니즘에 대한 간략한 설명은 아래를 참조하십시오.

따라서 특정 예에서 python 버전은 실제 완료 시간에 비해 더 빠릅니다. 그러나 파이썬 접근법은 커널 공간에서 더 많은 시간을 소비하여 커널 함수를 호출합니다. 이 bc명령은 본질적으로 커널 공간에서 시간을 소비하지 않으며 모든 시간은 사용자 공간에서 소비되며 아마도 내부 bc코드를 실행 합니다.

이것은 당신에게 아무런 차이가 없습니다. 실제로 당신이 정말로 관심을 갖는 유일한 정보 real는 명령을 실행하고 출력을 얻는 데 걸리는 실제 시간입니다.

또한 이러한 작은 차이는 안정적이지 않으며 시스템로드에 따라 달라지며 명령을 실행할 때마다 변경됩니다.

$ for i in {1..10}; do ( time python test.py > /dev/null ) 2>&1; done | grep user
user    0m0.056s
user    0m0.052s
user    0m0.052s
user    0m0.052s
user    0m0.060s
user    0m0.052s
user    0m0.052s
user    0m0.056s
user    0m0.048s
user    0m0.056s

$ for i in {1..10}; do ( time echo 6^6^6 | bc > /dev/null ) 2>&1; done | grep user
user    0m0.188s
user    0m0.188s
user    0m0.176s
user    0m0.176s
user    0m0.172s
user    0m0.176s
user    0m0.180s
user    0m0.172s
user    0m0.172s
user    0m0.172s

10

다른 관점에서 설명하겠습니다.

공평하게 말하면, bc디스크에서 아무것도 읽을 필요가 없으며 블로 브 / 바이너리 만 필요하기 때문에 파이썬은 일련의 모듈을 가져와 파일을 읽어야하기 때문에 이점이 있습니다. 따라서 테스트가쪽으로 치우칠 수 있습니다 bc. 실제로 테스트하려면 사용해야하는 bc -q file경우 file포함

6^6^6
quit

그 변경으로 사용 시간이 수정되었습니다 echo.

bc  0.33s user 0.00s system 80% cpu 0.414 total

파일을 사용하려면

bc -q some  0.33s user 0.00s system 86% cpu 0.385 total

(더 큰 차이를 알기 위해서는 terdon의 방법을 사용해야하지만 적어도 우리는 그것들을 알고 있습니다)

이제 파이썬 관점에서 파이썬은 디스크에서 파일을 읽고, 파일을 컴파일 할 때마다 컴파일 하고 실행해야하며, Andrew 포인트로 모듈을로드해야 하므로 실행 시간이 느려집니다. 파이썬 스크립트의 바이트 코드를 컴파일하면 코드를 실행하는 데 총 시간이 50 % 단축됩니다.

python some.py > /dev/null  0.25s user 0.01s system 63% cpu 0.413 total

컴파일 :

./some.pyc  0.22s user 0.00s system 77% cpu 0.282 total

보시다시피, 서로 다른 도구 간의 시간 실행에 영향을 줄 수있는 몇 가지 요소가 있습니다.


3

다른 답변을 읽는 이점이 있습니다. 우리는 여기에 같은 거대한 정수 나왔습니다 거래 둘 것을 왜 나 같은 우선 사람들이 이유를 알고 있어야 위해 Python그리고 bc권리 연관 이 아니라고 거듭 제곱을 확장하는 수단 6^36우리가 평가하고 오히려 6^46656상당히 큰있다. 1

다음 명령에서 변형을 사용하여 time예약어 및 명령 출력의 특정 요소에 대한 평균을 추출 할 수 있습니다 .

for i in {1..1000}; do (time echo 6^6^6 | bc > /dev/null) 2>&1; done | grep 'rea' | sed -e s/.*m// | awk '{sum += $1} END {print sum / NR}'

for i in {1..1000}; do (/usr/bin/time -v sh -c 'echo 6^6^6 | bc > /dev/null') 2>&1; done | grep 'Use' | sed -e s/.*:// | awk '{sum += $1} END {print sum / NR}'

다른 경로로 이동하여 파일을 비교에서 완전히 제거 할 수 있습니다. 또한 역사적 으로 전자는 "프론트 엔드 프로세서"이기 때문에 bc의 타이밍을 dc명령 과 비교할 수 있습니다 . 다음 명령이 시간이 초과되었습니다.

echo 6^6^6 | bc
echo 6 6 6 ^ ^ p | dc
echo print 6**6**6 | python2.7

참고 dc명령은 왼쪽 연관되어 지수합니다. 2

time1000 반복 (초) 동안 (bash)에 대한 결과가 있습니다 .

0.229678 real bc
0.228348 user bc
0.000569 sys bc
0.23306  real dc
0.231786 user dc
0.000395 sys dc
0.07 real python
0.065907 user python
0.003141 sys python

bc그리고 dc이러한 맥락에서 유사한 성능을 제공합니다.

덜 정확한 3 개 의 결과 /usr/bin/time즉, GNU time명령 (규모의 정밀도는 여기 유효하지 않습니다하지만 결과는 유사하다) :

0.2224 user bc
0 sys bc
0.23 Elapsed bc
0.22998 user dc
0 sys dc
0.23 Elapsed dc
0.06008 user python
0 sys python
0.07 Elapsed python

장점은 궁극적으로 유용 할 수있는 훨씬 더 많은 정보를 /usr/bin/time제공하는 -v옵션을 제공한다는 것 입니다.

파이썬 모듈 과 대화하기 위해 이것을 내부적 으로 평가하는 것도 가능 timeit합니다 :

python2.7 -m timeit -n 1000 -r 1 'print 6**6**6' | grep 'loops'
1000 loops, best of 1: 55.4 msec per loop

그것은 우리가 전에 보았던 것보다 조금 빠릅니다. 통역사 자체를 시험해 봅시다 :

>>> import timeit
>>> import sys
>>> import os
>>> T = timeit.Timer("print 6**6**6")
>>> n = int(1000)
>>> f = open(os.devnull, 'w')
>>> sys.stdout = f
>>> t = t.timeit(n)
>>> sys.stdout = sys.__stdout__
>>> print t/n
0.0553743481636

내가 본 것 중 가장 빠릅니다.


우리가보다 적은 지수를 평가 6^6하면 time for명령어는 우리가 사용한 것과 같은 루프 명령어를 사용 하여 놀라운 결과를 낳습니다 .

0.001001 bc real
0.000304 user
0.000554 sys
0.014    python real i.e. 10x more than bc??
0.010432 user
0.002606 sys

따라서 작은 정수 bc를 사용하면 갑자기 훨씬 빠릅니다. 시스템 재부팅에서 두 번째 실행까지 차이가 ​​없습니다. 그러나 동시에 timeit파이썬에 사용하면 다음과 같은 이점이 있습니다.

python2.7 -m timeit -n 100000 -r 1 'print 6**6' | grep loops  
100000 loops, best of 1: 0.468 usec per loop

이것은 밀리 초가 아닌 마이크로 초 이므로 for루프를 사용하는 훨씬 느린 결과와 일치하지 않습니다 . 이것을 테스트하기 위해 다른 도구가 필요할 수도 있고 다른 사람들이 설명했듯이 여기에서 눈을 맞추는 것 이상이 있습니다. 그것은 질문의 시나리오에서 파이썬이 더 빠른 것처럼 보이지만 그 이상으로 결론을 도출 할 수 있는지 확실하지 않습니다 ...


1. 에코의 산술 확장 즉, 같은의 범위를 넘어 말할 필요도없이 echo $((6**6**6))- bash또한, 즉 바로 연관 될 일이 6^6^6 = 6^(6^6).

2. 이것과 비교하십시오 : 6 6 ^ 6 ^ p.

3. GNU time 명령은 BSD UNIX에서 실행될 때 더 많은 정보를 제공 할 수 있습니다 (GNU 시간 정보 문서) : 'time'으로 표시되는 대부분의 정보는 'wait3'시스템 호출에서 파생됩니다. 숫자는 'wait3'에 의해 반환 된 숫자만큼만 유효합니다. 많은 시스템이 '시간'이보고 할 수있는 모든 리소스를 측정하지는 않습니다. 해당 자원은 0으로보고됩니다. 대부분 또는 모든 리소스를 측정하는 시스템은 4.2 또는 4.3BSD를 기반으로합니다. 이후의 BSD 릴리스는 더 적은 리소스를 측정하는 다른 메모리 관리 코드를 사용합니다. -상태 정보를 반환하는 'wait3'호출이없는 시스템에서는 'times'시스템 호출이 대신 사용됩니다. 'wait3'보다 훨씬 적은 정보를 제공하므로 해당 시스템에서 'time'은 대부분의 자원을 0으로보고합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.