python programming: tuning and optimization

19

Upload: chan-shik-lim

Post on 11-Apr-2017

155 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Python Programming: Tuning and Optimization

Python Intermediate Programming

임찬식 ([email protected])

1

Page 2: Python Programming: Tuning and Optimization

Python Intermediate Programming타입과 객체

함수와 함수형 프로그래밍

클래스와 객체지향 프로그래밍

데이터 구조

튜닝과 최적화

2

Page 3: Python Programming: Tuning and Optimization

튜닝과 최적화시간 측정

메모리 측정

프로파일링

튜닝 전략

3

Page 4: Python Programming: Tuning and Optimization

시간 측정

time.clock()현재 CPU 경과 시간 값을 얻어올 때 사용

time.time()실제 실행 시간을 얻어올 때 사용

timeit.timeit(code [, setup])매우 짧게 실행되는 문장에 �해서 시간을 측정할 때 사용

>>> from timeit import timeit>>> timeit('math.sqrt(2.0)', 'import math')0.11009419399488252>>> timeit('sqrt(2.0)', 'from math import sqrt')0.06311527400976047

4

Page 5: Python Programming: Tuning and Optimization

시간 측정

timeit('math.sqrt(2.0)', 'import math')

첫 번째 인수는 벤치마크하려는 코드

두 번째 인수는 실행 환경을 설정하기 위해 한 번만 실행될 문장

number=count 키워드 인수를 설정해 반복할 실행 횟수 지정

timeit() 함수는 벤치마크 코드를 100만 번 실행하고 경과 시간 보고

timeit.repeat(code [, setup])시간을 세 번 측정하고 결과를 리스트로 반환

>>> from timeit import repeat>>> repeat('math.sqrt(2.0)', 'import math')[0.09879132499918342, 0.09977803799847607, 0.09539347399550024>>> repeat('sqrt(2.0)', 'from math import sqrt')[0.0634966959914891, 0.060734901009709574, 0.05894679999619257

5

Page 6: Python Programming: Tuning and Optimization

메모리 측정

sys.getsizeof()개별 파이썬 객체 메모리 사용량을 바이트 단위로 반환

>>> import sys>>> sys.getsizeof(10)28>>> sys.getsizeof("Hello, World!")62>>> sys.getsizeof([1, 2, 3, 4])96>>> sum(sys.getsizeof(x) for x in [1, 2, 3, 4])112

리스트, 튜플, 사전 같은 컨테이너에 �해서 얻은 크기는컨테이너 객체 그 자체의 크기만을 의미

내부에 있는 모든 객체 크기를 계산하려면 sum() 을 이용

6

Page 7: Python Programming: Tuning and Optimization

프로그램 프로파일링

profile, cProfile프로파일 정보를 수집하는 데 사용되는 모듈

도달 범위(coverage) 분석성능 통계 정보 수집

명령줄에서 cProfile 실행

% python -m cProfile program.py

7

Page 8: Python Programming: Tuning and Optimization

프로그램 프로파일링

보고서 항목별 의미

항목 설명

primitive calls 비재귀 함수 호출 횟수

ncalls 총 호출 횟수(자신에 �한 호출도 포함)

tottime 이 함수에서 머무른 시간

percall tottime/ncalls

cumtime 이 함수에서 머무른 총 시간

percall cumtime/(primitive calls)

filename:lineno(function) 각함수의위치와이름

8

Page 9: Python Programming: Tuning and Optimization

튜닝 전략 : 프로그램 이해

최적화 하려는 코드를 먼저 프로파일링 후에 가장 시간을 많이사용하는 함수나 메서드에 초점을 맞추어 최적화 진행

드물게 호출되는 확실하지 않은 연산을 최적화하는 것은전체적인 속도 향상에 도움이 되지 않음

9

Page 10: Python Programming: Tuning and Optimization

튜닝 전략 : 알고리즘 이해

비효율적인 알고리즘을 최적화하기 보다는 더 나은 알고리즘 고민을 먼저

형편없이 구현된 O(n log n) 알고리즘이 잘 구현된 O (n^3) 보다는월등히 빠른 성능을 내는게 일반적

10

Page 11: Python Programming: Tuning and Optimization

튜닝 전략 : 내장 타입 사용

파이썬 내장 타입(튜플, 리스트, 집합, 사전)은 모두 C 로 구현되어빠른 성능을 보이므로 내장 타입을 활발하게 사용하고 데이터 구조를만들어 내장 데이터 타입을 흉내 내는 것은 비효율적

표준 라이브러리에 있는 타입도 필요한 상황에 맞게 사용

리스트 앞에 데이터를 추가하는 작업에는 collection.deque 사용 고려

리스트 가장 앞에 항목을 추가하면 모든 데이터를 옆으로 옮기는 비효율적인작업을 수행해야 하는데, 이 경우에는 deque 가 적절한 데이터 구조

>>> timeit('s.insert(0, 42)', 's=[]', number=100000)3.213872305001132>>> timeit('s.appendleft(42)', >>> 'import collections; s = collections.deque()', >>> number=100000)0.010021128007792868

11

Page 12: Python Programming: Tuning and Optimization

튜닝 전략 : 계층을 추가하지 않는 것

객체나 함수에 �해서 계층을 추가하는 것은 성능에 Ý향을 주기 때문에계층을 추가하는 것에 �해 고민하는 것이 필요

dict() 함수를 사용해서 문자열 키를 갖는 사전을 생성하는 것은따옴표를 제거하는 효과가 있지만, 성능에 Ý향을 줌

s = dict(name='GOOG',shares=100,price=450.10)# s = {'name':'GOOG','shares':100,'price':450.10} 와 동일

>>> timeit(... "s = {'name':'GOOG','shares':100,'price':450.10}")0.1306551239977125>>> timeit(... "s = dict(name='GOOG',shares=100,price=450.10)")0.3718919529928826

12

Page 13: Python Programming: Tuning and Optimization

튜닝 전략 : 사용자 정의 클래스와 인스턴스의 기반은 사전

인스턴스 데이터를 검색하고 설정하는 작업은 사전을직접 이용하는 것보다 �부분 느림

데이터를 저장하기 위한 간단한 자료 구조를 원한다면클래스 정의보다는 사전을 사용하는 것이 더 효율적

stock.py

class Stock(object): def __init__(self, name, shares, price): self.name = name self.shares = shares self.price = price

>>> timeit("s=Stock('GOOG',100,450.0)", >>> "from stock import Stock")0.5741711250011576>>> timeit("s={'name':'GOOG','shares':100,'price':450.0}")0.13291993999155238

13

Page 14: Python Programming: Tuning and Optimization

튜닝 전략 : __slots__ 사용

프로그램에서 사용자 정의 클래스 인스턴스를 다수 생성할 경우에는__slots__ 속성을 이용해 사전을 사용하지 않는 것 고려

stock.py

class StockSlots(object): __slots__ = ['name', 'shares', 'price'] def __init__(self, name, shares, price): self.name = name self.shares = shares self.price = price

__slots__ 을 사용하면 인스턴스 데이터를 사전이 아닌 자료 구조에 저장

>>> timeit("s=Stock('GOOG',100,450.0)", "from stock import Stock"0.5932310930074891>>> timeit("s=StockSlots('GOOG',100,450.0)", "from stock import StockSlots"0.4837448360049166

14

Page 15: Python Programming: Tuning and Optimization

튜닝 전략 : 점(.) 연산자 사용 자제

객체 속성을 찾을 때 점(.) 연산자를 사용하면 항상 이름 검색이 수행

메서드 검색이나 모듈 검색이 잦은 경우에는 지역 변수를 사용해속성 검색 연산을 제거하는 것이 효율적

>>> timeit("math.sqrt(5.0)", "import math")0.0976861710078083>>> timeit("sqrt(5.0)", "from math import sqrt")0.06044331699376926

속성 검색을 제거하는 것이 가독성에 Ý향을 줄 수 있으므로성능이 중요한 곳에서 사용하는 것이 좋음

15

Page 16: Python Programming: Tuning and Optimization

튜닝 전략 : 예외 처리

흔하게 발생하지 않는 경우를 처리하기 위해서 예외를 사용

예외를 잘 발생시키지 않는 코드를 try 블록으로 처리

if 문을 이용해 잘 발생하지 않는 조건을 검색하는 것은비효율적

흔한 경우에 �한 예외 처리는 피하는 형태로 구현

흔하게 발생하는 예외는 조건을 직접 검사하는 방식이 효율적

16

Page 17: Python Programming: Tuning and Optimization

튜닝 전략 : 예외 처리

get_item.py

def get_item_try(items, key): try: value = items[key] except KeyError: value = None return value

def get_item_in(items, key): if key in items: value = items[key] else: value = None return value

17

Page 18: Python Programming: Tuning and Optimization

튜닝 전략 : 예외 처리

>>> timeit("get_item_try({'a': 10, 'b': 20}, 'c')", >>> "from get_item import get_item_try")0.6027262949937722>>> timeit("get_item_in({'a': 10, 'b': 20}, 'c')", >>> "from get_item import get_item_in")0.26192101500055287

18

Page 19: Python Programming: Tuning and Optimization

튜닝 전략 : 함수형 프로그래밍

데이터 처리를 수행할 때 리스트 내포와 생성기 표현식은 직접 데이터에 �해반복을 수행하는 연산에 비해 효율적

생성기를 사용해 더 빠르면서 메모리를 효율적으로 사용하는 코드 작성 가능

19