한 줄씩 Python 코드 프로파일링
이 문서에서는 Python 코드를 한 줄씩 프로파일링하고 코드 실행에 대한 유용한 정보를 얻는 방법을 설명합니다.
먼저 프로파일링에 대해 간단히 소개하겠습니다. 그런 다음 함수 기반 프로파일링보다 라인별 프로파일링을 사용하는 것이 더 나은 경우에 대해 논의할 것입니다. 그런 다음 Python에서 프로파일링 구현에 대해 논의합니다.
프로파일링이란
프로파일링은 코드의 다른 부분에서 사용하는 리소스를 확인하는 프로세스입니다. 효율적인 코딩 관행을 위해 우리는 일반적으로 시간 복잡도(다른 코딩 단위/기능에 걸리는 시간) 또는 메모리 복잡성(다른 코딩 단위/기능에 의한 메모리 활용)에 주로 관심을 둡니다.
전자는 프로그램 소요 시간을 줄이는 데 집중하는 데 도움이 되고 후자는 메모리 사용을 최적화하는 데 도움이 됩니다.
함수 프로파일링
주로 모든 언어에서 기능 수준 프로파일링은 프로그램의 여러 기능에서 소비되는 시간을 찾는 데 사용됩니다. 따라서 Python 기본 패키지에는 함수 프로파일링을 위한 라이브러리 cProfile
및 Profile
이 이미 포함되어 있습니다.
라인 프로파일러
함수 기반 프로파일러는 다양한 함수에 소요된 시간에 대한 정보를 제공합니다. 그러나 함수 또는 프로그램이 차지하는 전체 시간에 어떤 라인이 더 많이 기여하는지 확인하기 위해 라인 기반 시간 복잡도가 필요한 경우가 있습니다.
이러한 경우를 위해 Python에 line_profiler
라이브러리가 있습니다.
line_profiler
모듈을 사용하여 Python 코드 프로파일링
LineProfiler
모듈을 사용하면 라인별로 또는 기능별로 코드를 프로파일링할 수 있습니다.
다음 Python 코드 스니펫에서 slow_avg_producer()
및 fast_average_producer()
라는 두 개의 함수를 만들었습니다. 이 두 함수는 모두 동일한 평균을 생성하지만 실행 시간은 다릅니다.
먼저 다음 모듈을 설치하여 라인 프로파일러를 사용하여 코드를 프로파일링합니다.
!pip install line_profiler
import time
import random
def slow_avg_producer():
time.sleep(6) # Do nothing for 5 time units
# generate random numbers array
arr = [
random.randint(1, 100) for i in range(10000)
] # generate random numbers array
return sum(arr) / len(arr)
def fast_average_producer():
time.sleep(1) # Do nothing for 1 time units
# generate random numbers array
arr = [random.randint(1, 100) for i in range(10000)]
return sum(arr) / len(arr)
def main_func():
average = slow_avg_producer()
print(average)
result = fast_average_producer()
print(average)
타이밍 통계를 얻기 위해 먼저 LineProfiler
개체를 생성한 다음 main_func()
를 통과하여 래퍼를 가져옵니다. 결국 프로파일링 통계를 얻을 수 있습니다.
from line_profiler import LineProfiler
line_prof = LineProfiler()
line_prof_wrapper = line_prof(main_func)
line_prof_wrapper()
# print the profiling details
line_prof.print_stats()
위의 코드는 다음 출력을 생성합니다. 시간 단위는 마이크로초입니다.
Timer unit: 1e-06 s
Total time: 7.10521 s
File: <ipython-input-14-67ae2a9633ee>
Function: main_func at line 17
Line # Hits Time Per Hit % Time Line Contents
==============================================================
17 def main_func():
18 1 6054801.0 6054801.0 85.2 average = slow_avg_producer()
19 1 676.0 676.0 0.0 print(average)
20
21 1 1049070.0 1049070.0 14.8 result = fast_average_producer()
22 1 659.0 659.0 0.0 print(average)
통계에 따르면 메인 함수에서 slow_avg_producer()
는 6.054초가 걸리고 다음 print
문은 0.000676초가 걸립니다. 반면 fast_average_producer()
는 시간이 훨씬 적게 걸립니다.
명령줄을 통해 Python 코드 프로파일링
명령줄 인터페이스를 사용하여 함수의 라인별 프로파일링 세부 정보를 얻을 수 있습니다. 이 방법에서는 kernprof
명령을 사용합니다.
각 함수의 시작 부분에 @profile
데코레이터를 추가한다는 점을 제외하면 여기에서도 동일한 기능을 사용할 것입니다. 이 스크립트의 이름을 average_producer.py
로 지정합니다.
import time
import random
@profile
def slow_avg_producer():
time.sleep(6) # Do nothing for 5 time units
# generate random numbers array
arr = [
random.randint(1, 100) for i in range(10000)
] # generate random numbers array
return sum(arr) / len(arr)
@profile
def fast_average_producer():
time.sleep(1) # Do nothing for 1 time units
# generate random numbers array
arr = [random.randint(1, 100) for i in range(10000)]
return sum(arr) / len(arr)
@profile
def main_func():
average = slow_avg_producer()
print(average)
result = fast_average_producer()
print(average)
main_func()
kernprof
명령을 사용하여 다음 명령을 사용하여 line-profiler
모듈을 설치해야 합니다.
pip install line-profiler
Colab 또는 Jupyter Notebook 터미널의 경우 위 명령의 시작 부분에 강타 기호(!
)를 사용합니다.
설치 후 kernprof.exe
가 설치된 디렉토리를 변경해야 합니다. 그런 다음 다음 명령을 실행합니다.
kernprof
는 cProfile
을 수행할 수 있는 옵션을 제공하지만 여기서는 라인 프로파일러를 사용합니다. 이를 위해 -l
인수가 사용됩니다.
kernprof -l average_producer.py
다음 명령을 실행하여 프로파일링 결과를 확인합니다.
python -m line_profiler average_producer.py.lprof
아래와 같이 명령줄 인터페이스에 프로파일링 결과를 인쇄합니다.