새소식

반응형
Python/성능

Python 성능 향상: 3배 더 빠른 스크립트로 바꾸는 방법

  • -
반응형

 

python 성능 향상 img generated by AI

Python 코드가 느려서 답답한 경험, 누구나 한 번쯤 있죠? 

제가 사용한 주요 Python 성능 최적화 방법들을 공유하려고 합니다. 이 방법들을 통해 여러분도 Python 스크립트를 빠르게 만들 수 있을 것입니다.


1. 성능 병목 구간 찾기: 프로파일링부터 시작

성능을 개선하기 전에, 무엇이 문제인지를 아는 것이 가장 중요합니다. 코드에서 병목이 되는 부분을 정확히 찾아내야 효과적인 최적화를 할 수 있죠. 이를 위해 Python의 cProfile을 사용해 프로파일링을 진행해봅시다.

import cProfile

def process_file():
    # 로그 파일 처리
    read_log_file()
    analyze_data()

def read_log_file():
    # 파일 읽기 작업
    pass

def analyze_data():
    # 데이터 분석 작업
    pass

if __name__ == "__main__":
    cProfile.run('process_file()')

cProfile을 사용하면, 각 함수가 호출된 횟수와 실행 시간을 알 수 있어 성능 저하의 원인을 파악하는 데 유용합니다.

반응형

2. 내장 함수 활용하기

Python의 내장 함수들은 대부분 C로 구현되어 있어 성능이 매우 뛰어납니다. 반복문을 직접 작성하기보다는 내장 함수를 사용하는 것이 성능을 높이는 지름길이죠. 예를 들어, collections.Counter를 사용하면 리스트에서 아이템의 빈도수를 쉽게 계산할 수 있습니다.

from collections import Counter

# 리스트에서 아이템 빈도수 계산
word_counts = Counter(words_list)

직접 반복문을 작성하는 것보다 한 줄로 간단히 해결할 수 있어 코드도 깔끔해지고 성능도 향상됩니다.


3. NumPy로 반복 연산 최적화하기

수치 연산이 많이 포함된 작업에서는 NumPy를 사용하는 것이 아주 큰 차이를 만들어냅니다. NumPy는 C로 작성된 배열을 사용하여 빠른 수치 연산을 지원합니다. 예를 들어, 리스트 컴프리헨션으로 값을 두 배로 만드는 작업은 NumPy로 처리하면 훨씬 빠릅니다.

import numpy as np

# NumPy 배열 생성 후 연산
numbers = np.linspace(1, 1_000_000, num=1_000_000)
doubled_numbers = numbers * 2

이렇게 NumPy를 사용하면, 수백만 개의 데이터 처리도 순식간에 끝납니다.


4. 리스트 컴프리헨션 활용하기

단순한 변환 작업이라면 전통적인 for 루프 대신 리스트 컴프리헨션을 사용하는 것이 더 효율적입니다. 컴프리헨션은 내부적으로 C로 최적화되어 있어 성능이 좋습니다.

# 전통적인 방법
squares = []
for num in range(10_000):
    squares.append(num**2)

# 리스트 컴프리헨션
squares = [num**2 for num in range(10_000)]

간결한 코드로 성능도 향상되므로, 가능하면 리스트 컴프리헨션을 사용하는 것이 좋습니다.


5. Numba로 JIT 컴파일 사용하기

수학적인 연산이 많은 코드에서는 Numba의 JIT(Just-In-Time) 컴파일러를 활용하면 성능을 크게 개선할 수 있습니다. Numba는 Python 코드를 기계어로 컴파일하여 실행 속도를 비약적으로 향상시킵니다.

from numba import jit

@jit
def calculate_square_and_cube(data):
    result = 0
    for number in data:
        result += number**2 + number**3
    return result

Numba를 사용하면 복잡한 수학 연산이 포함된 코드도 훨씬 더 빠르게 실행됩니다.


6. 반복 계산 결과 캐싱하기

자주 호출되는 계산 함수는 functools.lru_cache를 활용해 캐싱하면 성능을 크게 개선할 수 있습니다. 이미 계산한 값을 저장해두고, 다시 같은 계산을 할 때는 캐시된 값을 사용하는 방식입니다.

from functools import lru_cache

@lru_cache(maxsize=None)
def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n - 1)

반복되는 함수 호출에서 캐싱을 적용하면, 성능이 크게 향상됩니다.


7. 더 효율적인 데이터 구조 사용하기

리스트에서 in 연산을 사용해 반복적으로 요소를 찾는 작업은 비효율적입니다. 이럴 땐 set이나 dict를 사용하면 훨씬 빠른 검색이 가능합니다.

# 비효율적인 방식
if item in large_list:
    ...

# 더 효율적인 방식
large_set = set(large_list)
if item in large_set:
    ...

set은 평균적으로 O(1)의 시간 복잡도를 가지고 있어 큰 데이터에서도 빠른 검색을 보장합니다.


8. 병렬 처리 활용하기

여러 CPU 코어를 사용할 수 있다면, multiprocessing이나 joblib을 활용해 작업을 병렬로 처리하는 것이 성능을 크게 개선할 수 있는 방법입니다.

from multiprocessing import Pool

def compute_square(number):
    return number ** 2

if __name__ == "__main__":
    data = range(1_000_000)
    with Pool(4) as pool:
        results = pool.map(compute_square, data)

멀티코어 환경에서는 병렬 처리가 매우 유효합니다.


9. 전역 변수 피하기

전역 변수는 Python이 여러 네임스페이스에서 검색해야 하므로 성능을 저하시킬 수 있습니다. 지역 변수를 사용하면 성능을 개선하고, 코드도 더 깔끔해집니다.

# 전역 변수 사용
counter = 0

def update_counter(data):
    global counter
    for item in data:
        counter += 1

# 지역 변수 사용
def update_counter(data):
    local_counter = 0
    for item in data:
        local_counter += 1
    return local_counter

전역 변수를 피하고 지역 변수로 대체하는 것이 성능 개선에 도움이 됩니다.


10. Python 인터프리터 선택

PyPy는 JIT 컴파일러를 포함한 Python 인터프리터로, 숫자 계산이 많은 코드에서 성능을 크게 향상시킬 수 있습니다. CPython에 비해 상당한 성능 향상을 기대할 수 있습니다.

pypy my_script.py

PyPy는 특히 수학 연산이 많은 코드에서 뛰어난 성능을 발휘합니다.


결론

Python 성능 최적화는 단순히 코드를 더 효율적으로 만드는 작업이 아니라, 올바른 도구와 기법을 활용하는 과정입니다. 프로파일링을 통해 병목 구간을 찾아내고, NumPy, Numba, 캐싱, 병렬 처리 등을 적절히 조합하면 실행 속도를 크게 개선할 수 있습니다. 이러한 방법들을 활용하여 여러분의 Python 코드를 더 빠르고 효율적으로 만들어 보세요!

 

같이보면 좋은글

[Python/성능] - FastAPI 성능 최적화하기

 

FastAPI 성능 최적화하기

FastAPI 애플리케이션의 성능을 개선하기 위해 많은 자료를 찾아보고 정리해봅니다.예제 소개다음은 FastAPI의 기본적인 엔드포인트 예제입니다. Product라는 Pydantic 모델을 정의하고, products 리스트

intelloper.tistory.com

[Python/성능] - [Python 성능] 🏎️ TTLCache vs DiskCache: 이미지 캐싱 속도 비교와 최적화 방법

 

[Python 성능] 🏎️ TTLCache vs DiskCache: 이미지 캐싱 속도 비교와 최적화 방법

이미지 또는 대용량 데이터를 빠르게 로드하려면 캐싱(Cache) 을 활용해야 합니다. 그런데 FastAPI에서 이미지를 캐싱할 때, TTLCache(메모리 캐시)와 DiskCache(디스크 캐시) 중 어떤 것이 더 나을까요?✔

intelloper.tistory.com

[Python/성능] - (Python 성능 향상) concurrent.futures 동시 프로그래밍 모듈로 속도 개선해보자!

 

(Python 성능 향상) concurrent.futures 동시 프로그래밍 모듈로 속도 개선해보자!

성능에 대해서는 프로그램을 만들고 나서나 기능 개발이 완료되고 나서나 작동이 잘되는것을 확인했는데 속도가 아쉽다면 항상 고민을 하게 됩니다.우리는 더 나은 품질에 빠릿빠릿한 프로그

intelloper.tistory.com

 

 

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.