한 줄씩 Python 코드 프로파일링

Hafiz Muhammad Zohaib 2024년2월15일
  1. 프로파일링이란
  2. line_profiler 모듈을 사용하여 Python 코드 프로파일링
  3. 명령줄을 통해 Python 코드 프로파일링
한 줄씩 Python 코드 프로파일링

이 문서에서는 Python 코드를 한 줄씩 프로파일링하고 코드 실행에 대한 유용한 정보를 얻는 방법을 설명합니다.

먼저 프로파일링에 대해 간단히 소개하겠습니다. 그런 다음 함수 기반 프로파일링보다 라인별 프로파일링을 사용하는 것이 더 나은 경우에 대해 논의할 것입니다. 그런 다음 Python에서 프로파일링 구현에 대해 논의합니다.

프로파일링이란

프로파일링은 코드의 다른 부분에서 사용하는 리소스를 확인하는 프로세스입니다. 효율적인 코딩 관행을 위해 우리는 일반적으로 시간 복잡도(다른 코딩 단위/기능에 걸리는 시간) 또는 메모리 복잡성(다른 코딩 단위/기능에 의한 메모리 활용)에 주로 관심을 둡니다.

전자는 프로그램 소요 시간을 줄이는 데 집중하는 데 도움이 되고 후자는 메모리 사용을 최적화하는 데 도움이 됩니다.

함수 프로파일링

주로 모든 언어에서 기능 수준 프로파일링은 프로그램의 여러 기능에서 소비되는 시간을 찾는 데 사용됩니다. 따라서 Python 기본 패키지에는 함수 프로파일링을 위한 라이브러리 cProfileProfile이 이미 포함되어 있습니다.

라인 프로파일러

함수 기반 프로파일러는 다양한 함수에 소요된 시간에 대한 정보를 제공합니다. 그러나 함수 또는 프로그램이 차지하는 전체 시간에 어떤 라인이 더 많이 기여하는지 확인하기 위해 라인 기반 시간 복잡도가 필요한 경우가 있습니다.

이러한 경우를 위해 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 터미널의 경우 위 명령의 시작 부분에 강타 기호(!)를 사용합니다.

line-profiler 설치

설치 후 kernprof.exe가 설치된 디렉토리를 변경해야 합니다. 그런 다음 다음 명령을 실행합니다.

kernprofcProfile을 수행할 수 있는 옵션을 제공하지만 여기서는 라인 프로파일러를 사용합니다. 이를 위해 -l 인수가 사용됩니다.

kernprof -l average_producer.py

kernprof

다음 명령을 실행하여 프로파일링 결과를 확인합니다.

python -m line_profiler average_producer.py.lprof

아래와 같이 명령줄 인터페이스에 프로파일링 결과를 인쇄합니다.

파이썬 라인 프로파일러

프로파일링 결과

관련 문장 - Python Profile