실무에 사용한 데이터 엔지니어링 스킬에 대한 정리내용입니다.
개인적인 기록을 위해 작성하였습니다.
https://github.com/mjs1995/muse-data-engineer/tree/main/doc/Programming%20Language
Python 개요
- 파이썬은 고수준 언어이면서 배터리 포함이라는 개념하에 다양한 도구를 기본 제공하므로 누구나 쉽게 데이터 전처리나 데이터 분석에 사용할 수 있습니다.
- 파이썬을 쓰는 이유
- 표현력이 좋고 배우기 쉽습니다.
- 많은 파이썬 라이브러리는 타 언어로 작성된 도구를 감싸서 다른 시스템을 쉽게 호출합니다.
- 주된 강점 하나는 빠른 프로토타이핑, 비록 처음부터 그럴싸하지는 않더라도 다양한 라이브러리를 활용해서 실현 가능한 아이디어인지 빠르게 검증해볼 수 있습니다.
- 파이썬 개선점
- 멀티 스레딩이 안 되서 멀티 프로세싱을 해야 하며 다른 스크립트 언어들처럼 개발은 빠른데 유지보수하기에 힘든 부분이 존재합니다.
- 내부적으로 잘 최적화된 명령어 집합을 실행하지만, 명령어 집합을 올바른 순서로 실행하도록 하면 성능이 더 좋아집니다.
- 글로벌 인터프리틱 락(Global Interpreter Lock - GIL) 때문에 코어를 여러 개 활용하기가 쉽지 않습니다. GIL을 현재 사용중인 코어가 몇 개든, 한 번에 명령 하나만 실행하도록 강제합니다. 파이썬에서 동시에 여러 개의 코어에 접근하더라도 한 번에 파이썬 명령 하나만 실행됩니다.
- 다른 표준 라이브러리인 multiprocessing 모듈을 사용하거나, numpy나 numexpr, 사이썬 같은 기술을 이용하거나, 분산 컴퓨팅 모델을 사용하는 방법으로 해결할 수 있습니다.
- 파이썬이 메모리를 자동으로 할당하고 해제하는 가비지 컬렉터(garbage collector GC)를 사용하기 때문, CPU 캐시에 데이터를 전송하는 데 영향을 미치는 메모리 단편화를 일으킵니다. 게다가 어디에서도 메모리에 저장되는 자료구조를 직접 변경할 수 없으므로 버스 폭이 아주 넓더라도 한 번의 계산에 필요한 정보를 한 번에 전송할 수 없습니다.
- 파이썬이 동적 타입을 사용하며 컴파일되지 않는다는 점
- 정적인 코드를 컴파일 할 때, 컴파일러는 CPU가 특정 명령을 실행하는 방식을 포함한 많은 부분을 변경해서 최적화 할 수 있습니다. 파이썬은 컴파일되지 않는 데다가 코드의 기능이 런타임에 변경되는 동적 타입 언어라 최적화 알고리즘이 제 기능을 발휘하기 어렵습니다. 이 문제를 극복하는 여러 방법 중 사이썬(Cython)이 가장 대표적, 사이썬은 파이썬 코드를 컴파일하고 컴파일러에게 동적인 코드가 실제로 어떻게 동작하는지 힌트를 줄 수 있습니다.
- 파이썬 최적화
- 코드 최적화: 파이썬 코드를 최적화하여 더 빠르게 실행하도록 합니다. 이를 위해, 루프를 최적화하거나, 불필요한 계산을 제거하거나, 적절한 자료구조를 사용하는 등의 방법을 적용할 수 있습니다. 코드를 최적화하는 방법은 파이썬 내장 모듈인 cProfile을 사용하여 코드 실행 시간을 측정하고, 최적화가 필요한 부분을 파악한 후, 알고리즘과 자료구조를 개선하는 등의 방법을 적용할 수 있습니다.
- JIT 컴파일러 사용: 파이썬은 인터프리터 언어이기 때문에, 실행 시간이 오래 걸리는 코드가 있을 수 있습니다. 이를 해결하기 위해 JIT(Just-In-Time) 컴파일러를 사용할 수 있습니다. JIT 컴파일러는 코드를 실행하는 동안 중간 언어로 번역하여, 코드 실행 속도를 높입니다.
- 병렬 처리: 파이썬 코드를 여러 개의 프로세스나 쓰레드로 분할하여 병렬 처리할 수 있습니다. 이를 통해 CPU의 다중 코어를 활용하여 코드 실행 속도를 높일 수 있습니다.
- C 모듈 사용: 파이썬의 일부 기능은 C 언어로 구현되어 있습니다. 따라서, C 모듈을 사용하여 코드 실행 속도를 높일 수 있습니다.
- PyPy 사용: PyPy는 파이썬 인터프리터의 대체 구현체로, JIT 컴파일러를 내장하고 있어 파이썬 코드 실행 속도를 향상시킬 수 있습니다.
프로파일링
- 프로파일링으로 병목 지점을 찾아 최소한의 노력으로 성능을 최대한 끌어올릴 수 있습니다.
- 효과적으로 프로파일하기
- 프로파일링의 첫 번째 목표는 시스템의 어느 부분이 느린지, 어디서 RAM을 많이 쓰는지, 디스크 I/O나 네트워크 I/O를 과도하게 발생시키는 부분이 어디인지를 확인하는 것입니다.
- 기본적인 프로파일링 기법은 IPython의 %timeit 매직 명령어와 time.time(), 데커레이터(decorator)를 활용한 시간 측정입니다.
- line_profiler는 각 줄을 몇번 실행했는지, 총 소요 시간은 얼마인지를 검사함, 이는 어느 부분이 왜 느린지를 이해할 수 있는 정보
- CPU에서 실행된 명령의 수와 CPU 캐시가 얼마나 효율적으로 활용되었는지 알아볼 수 있는 perf stat 사용법을 배웁니다. 이 정보는 매트릭스 연산을 튜닝하는 고급 기번에 활용됩니다.
- C파이썬 내부에 쓰이는 파이썬 바이트코드 알면 파이썬 내부를 더 잘 이해할 수 있습니다. 파이썬의 스택 기반 가상 머신을 이해하면 왜 특정 코딩 습관이 코드를 느리게 하는지를 알 수 있습니다.
- 시간을 측정하는 간단한 방법 : print와 데커레이터
- 데커레이터는 print 문보다 조금 더 깔끔한 방법으로 시간을 측정하려는 함수 위에 코드를 한 줄 추가합니다.
- 가변 길이 인자인 *args와 키워드 인자인 **kwargs를 받아, 실행하는 fn 함수로 넘겨줍니다.
- @wraps(fn)을 사용해서 데커레이터로 넘겨온 함수 이름과 독스트링을 호출하는 함수에서 확인할 수 있도록 합니다. 그렇지 않으면 데커레이터로 넘어온 함수가 아니라 데커레이터 함수 그 자체의 이름과 독스트링을 보게 됩니다.
- cProfile 모듈 사용하기
- 표준 라이브러리에 내장된 프로파일링 도구로, C파이썬의 가상 머신 안에서 확인되는 모든 함수에 시간을 측정하는 장치를 연결합니다. 이는 큰 오버헤드를 유발하지만 그만큼 더 많은 정보를 제공합니다.
- profile은 순수 파이썬 기반의 프로파일러로 cProfile보다 느립니다.
- cProfile은 profile과 같은 인터페이스를 제공하며 오버헤드를 줄이려고 C로 작성합니다.
- 프로파일하기 전에 프로파일하려는 코드의 기대 속도에 대한 가설을 세우는 습관을 들여야합니다.
- SnakeViz로 cProfile 결과 시각화하기
- snakeviz는 cProfile로 생성한 통계 정보를 시각화하는 도구로 더 오랜 시간을 소비한 영역을 더 큰 상자로 표시하여 기존의 runsnake 도구를 대신합니다.
- 통계를 cumtime(누적 시간), percall(호출 당 비용), ncalls(호출 회수) 등의 지표 기준으로 정렬할 수 있습니다. cumtime을 기준으로 정렬하면 어떤 함수가 전체적으로 가장 많은 시간을 소모했는지 알 수 있습니다.
- line_profiler로 한 줄씩 측정하기
- line_profiler가 파이썬 코드에서 CPU 병목 원인을 찾아주는 가장 강력한 도구라 생각합니다.
- line_profiler는 개별 함수를 한 줄씩 프로파일하므로, 먼저 cProfile을 사용해서 어떤 함수를 line_profiler로 자세히 살펴볼지 정하면 됩니다.
- 코드를 수정하면서 line_profiler 결과에 버전을 기록해두면 변경 사항의 성공/실패 기록을 빠르게 참고할 수 있습니다.
- memory_profiler로 메모리 사용량 진단하기
- CPU 사용량을 측정하는 로버트 컨의 line_profiler 패키지처럼 메모리 사용량을 줄 단위로 측정해주는 memory_profiler가 있습니다.
- PySpy로 기존 프로세스 살펴보기
- py-spy는 새로운 샘플링 프로파일러(sampling profiler)로 코드를 변경하는 대신, py-spy는 이미 실행 중인 파이썬 프로세스를 들여다보고 콘솔에 top과 비슷한 방식으로 상황을 표시해 줍니다.
- py-spy는 러스터(Rust)로 작성됐고, 다른 프로세스를 들여다보려면 관리자 권한이 필요합니다.
Reference
'Data Engeneering > python' 카테고리의 다른 글
python multiprocessing (1) | 2023.03.06 |
---|---|
python Async (0) | 2023.03.05 |
python 컴파일 (0) | 2023.03.05 |