일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 알고리즘
- 프로그래머스
- target
- onClick
- Display
- with\
- sql
- AI
- AI 5기
- cte
- itertools
- 내일배움캠프
- venv
- googleappscript
- googlesheet
- git #github #내일배움캠프
- python
- 함수실행시간
- iterable
- 가상환경
- gitignore
- 우선순위
- vscode
- WIL
- position
- 함수성능평가
- Iterator
- Level1
- time()
- A태그
- Today
- Total
05의 개발 계발
[TIL] 230322 [python] 함수 실행 시간 측정 본문
TIL 학습목표
- python 에서 함수 실행 시간을 측정하는 방법을 안다.
- sort 함수의 type과 사용법을 안다.
1) 문제점 (Problem)
지난 TIL에서 알고리즘 문제를 풀고, 코드를 축약해보았다.
단순히 컴프리헨션을 사용하여 축약한 것이라 알고리즘이 변화한 것 같진 않지만,
그래도 축약했던 함수의 성능을 확인해보고 싶어졌다.
그래서 time() 을 사용하여 함수 실행 시간을 측정을 해보려 했다.
2) 시도해본 것들 (Try)
▶함수 실행 시간 측정 코드 짜기
한 파일에서 실행하기 위해 기존함수를 solution1 축약함수를 solution2 라고 정의했다.
기존함수==(solution1) / 축약함수==(solution2)
import time
answers=[1,2,3,4,5]
def solution1(answers):
#수포자 1,2,3을 a,b,c로 표현
a = [1,2,3,4,5]*2000 #10,000개의 배열 만들기 5*2000
b = [2,1,2,3,2,4,2,5]*1250 #10,000개의 배열 만들기 8*1250
c = [3,3,1,1,2,2,4,4,5,5]*1000 #10,000개의 배열 만들기 10*1000
count_a=0 #수포자1의 맞춘 갯수
count_b=0 #수포자2의 맞춘 갯수
count_c=0 #수포자3의 맞춘 갯수
for i, answer in enumerate(answers): #반복문 for 구문. 인덱스(i)로 순차배열 i는 0부터 시작한다
if answer == a[i]: #answers의 요소와 a의 요소를 비교하고, 맞을 경우
count_a += 1 #count_a에 1씩 더해준다
if answer == b[i]:
count_b += 1
if answer == c[i]:
count_c += 1
total=[count_a,count_b,count_c] #수포자1,2,3의 맞춘 개수를 total이라는 리스트로 저장
result=[] #문제에서 원하는 결과를 result 라고 표현
for i in range(0,3): #1,2,3 세 명이니 3번만 반복
if max(total) == total[i]: #공동이든 단독이든, 3명의 결과 중 가장 많이 맞춘경우
result.append(i+1) #수포자 번호에 맞는 번호를 리스트에 추가해라
result.sort() #리스트를 오름차순 정렬해라
return result
def solution2(answers):
spj1 = [1,2,3,4,5]*2000 #수포자1
spj2 = [2,1,2,3,2,4,2,5]*1250 #수포자2
spj3 = [3,3,1,1,2,2,4,4,5,5]*1000 #수포자3
spj = [spj1,spj2,spj3] #수포자리스트
score=[0,0,0] #수포자 점수 리스트
# 축약 코드 리스트 컴프리헨션
score=[sum(score[j] + 1 for i,answer in enumerate(answers) if answer == spj[j][i]) for j in range(0,3)]
#맞춘 문제수를 score에 리스트로 저장
No1=[k+1 for k in range(0,3) if max(score) == score[k]]
#맞춘 문제수를 비교하여 최고점의 수포자번호를 No1에 리스트로 저장
No1.sort() #No1 내림차순 정렬
return No1
# 기존함수 동작시간
start_time1 = time.time() #시작시간1 저장
solution1(answers) #기존함수동작
end_time1 = time.time() #종료시간1 저장
# 축약함수 동작시간
start_time2 = time.time() #시작시간2 저장
solution2(answers) #축약함수동작
end_time2 = time.time() #종료시간2 저장
# 코드가 종료된 시간 - 코드가 시작된 시간으로 실행 시간 구하기 (단위 : 초)
print(f"기존코드 실행 시간 : {end_time1-start_time1:.4f} 초")
print(f"축약코드 실행 시간 : {end_time2-start_time2:.4f} 초")
▶함수 실행 시간 측정하기
① 첫 번째 시도 : 입력값 5개 짜리 리스트 + 시간 소수 4째자리까지 출력
answers=[1,2,3,4,5]
# 코드가 종료된 시간 - 코드가 시작된 시간으로 실행 시간 구하기 (단위 : 초)
print(f"기존코드 실행 시간 : {end_time1-start_time1:.4f} 초") #소수점 4자리 까지
print(f"축약코드 실행 시간 : {end_time2-start_time2:.4f} 초") #소수점 4자리 까지
결과 : 비교가 불가하다. 자릿수를 늘려보자.
② 두 번째 시도: 입력값 5개 짜리 리스트 + 시간 소수 400째자리까지 출력
answers=[1,2,3,4,5]
# 코드가 종료된 시간 - 코드가 시작된 시간으로 실행 시간 구하기 (단위 : 초)
print(f"기존코드 실행 시간 : {end_time1-start_time1:.400f} 초") #소수점 400자리 까지
print(f"축약코드 실행 시간 : {end_time2-start_time2:.400f} 초") #소수점 400자리 까지
결과 : 비교가 불가하다. 입력값을 바꿔보자
③ 세 번째 시도: 입력값 1,000,000개 짜리 리스트 + 시간 소수 4째자리까지 출력
answers = [1, 2, 3, 4, 5] * 200000 # 100만개의 요소를 가진 리스트
a = [1, 2, 3, 4, 5] * 200000 # 1,000,000개의 배열 만들기 5*200000
b = [2, 1, 2, 3, 2, 4, 2, 5] * 125000 # 1,000,000개의 배열 만들기 8*125000
c = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] * 100000 # 1,000,000개의 배열 만들기 10*100000
결과 : 유의미한 차이가 나타났다. 비율을 내보자!
코드추가!
ratio = (end_time1 - start_time1) / (end_time2 - start_time2)
print(f"기존코드가 축약코드보다 {1/ratio:.4f}배 빠릅니다.")
<고찰>
*CPU의 성능에 따라 실행시마다 차이가 존재했다. 1.6~2.2배 정도 차이가 났으며, 기존코드가 더 빠르게 구동됐다.
* 같은 알고리즘을 축약했다고 생각했는데, 차이를 내는 요소가 있었던것 같다.
* 입력수가 작을 때는 CPU의 순간 성능이 큰 변수로 작용되어 기존코드가 더 느리게 실행되기도 했다.
3) 해결 (Solution)
Time() 과 입력값을 크게함으로, 함수 성능 차 확인!
▶전체코드
import time
answers = [1, 2, 3, 4, 5] * 200000 # 100만개의 요소를 가진 리스트
def solution1(answers):
# 수포자 1,2,3을 a,b,c로 표현
a = [1, 2, 3, 4, 5] * 200000 # 1,000,000개의 배열 만들기 5*200000
b = [2, 1, 2, 3, 2, 4, 2, 5] * 125000 # 1,000,000개의 배열 만들기 8*125000
c = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] * 100000 # 1,000,000개의 배열 만들기 10*100000
count_a = 0 # 수포자1의 맞춘 갯수
count_b = 0 # 수포자2의 맞춘 갯수
count_c = 0 # 수포자3의 맞춘 갯수
for i, answer in enumerate(answers): # 반복문 for 구문. 인덱스(i)로 순차배열 i는 0부터 시작한다
if answer == a[i]: # answers의 요소와 a의 요소를 비교하고, 맞을 경우
count_a += 1 # count_a에 1씩 더해준다
if answer == b[i]:
count_b += 1
if answer == c[i]:
count_c += 1
total = [count_a, count_b, count_c] # 수포자1,2,3의 맞춘 개수를 total이라는 리스트로 저장
result = [] # 문제에서 원하는 결과를 result 라고 표현
for i in range(0, 3): # 1,2,3 세 명이니 3번만 반복
if max(total) == total[i]: # 공동이든 단독이든, 3명의 결과 중 가장 많이 맞춘경우
result.append(i + 1) # 수포자 번호에 맞는 번호를 리스트에 추가해라
result.sort() # 리스트를 오름차순 정렬해라
return result
def solution2(answers):
spj1 = [1, 2, 3, 4, 5] * 200000 # 수포자1
spj2 = [2, 1, 2, 3, 2, 4, 2, 5] * 125000 # 수포자2
spj3 = [3, 3, 1, 1, 2, 2, 4, 4, 5, 5] * 100000 # 수포자3
spj = [spj1, spj2, spj3] # 수포자리스트
score = [0, 0, 0] # 수포자 점수 리스트
# 축약 코드 리스트 컴프리헨션
score = [
sum(score[j] + 1 for i, answer in enumerate(answers) if answer == spj[j][i])
for j in range(0, 3)
]
# 맞춘 문제수를 score에 리스트로 저장
No1 = [k + 1 for k in range(0, 3) if max(score) == score[k]]
# 맞춘 문제수를 비교하여 최고점의 수포자번호를 No1에 리스트로 저장
No1.sort() # No1 내림차순 정렬
return No1
# 기존함수 동작시간
start_time1 = time.time() #시작시간1 저장
solution1(answers) #기존함수동작
end_time1 = time.time() #종료시간1 저장
# 축약함수 동작시간
start_time2 = time.time() #시작시간2 저장
solution2(answers) #축약함수동작
end_time2 = time.time() #종료시간2 저장
# 코드가 종료된 시간 - 코드가 시작된 시간으로 실행 시간 구하기 (단위 : 초)
print(f"기존코드 실행 시간 : {end_time1-start_time1:.4f} 초")
print(f"축약코드 실행 시간 : {end_time2-start_time2:.4f} 초")
ratio = (end_time1 - start_time1) / (end_time2 - start_time2)
print(f"기존코드가 축약코드보다 {1/ratio:.4f}배 빠릅니다.")
4) 알게 된 점 (Learnd)
Time() 을 활용하여 함수 실행 시간을 측정하는 법을 익혔다.
단순한 함수일수록 실행시간이 매우 짧아 성능을 비교하기 힘들었다.
하나의 방법으로는, 입력값을 매우 크게하면 비교할 만큼 실행시간이 측정된다.
또 issue로는 입력값이 작을 때는, 실행 시 마다 기존코드가 빠를 때도, 축약코드가 빠를 때도 있었다.
구글링을 통해 원인을 찾아보니 순간순간의 CPU 성능에 따라 오차가 발생하는 부분이라, 이를 무시하기 위해서는 확실한 시간차가 존재하도록 (큰 입력값or 큰 반복수) 를 사용해야한다고 한다.
결과적으로 기존코드가 더 빠르기도하고, 코드리뷰 시 가독성 면에서도 좋다.
[결론]
성능면에서도 가독성면에서도, 무조건 짧다고 좋은 코딩이 아니다..!!
'TIL' 카테고리의 다른 글
[TIL] 230324 [python] iterable & iterator & itertools 의 관계 (0) | 2023.03.24 |
---|---|
[TIL] 230323 [python] .sort 와 sorted()의 차이 (Method 와 Function) (0) | 2023.03.23 |
[TIL] 230321 [알고리즘] [Python] Level1.모의고사 - 코드 축약 (1) | 2023.03.22 |
[TIL] 230320 [Python] or 연산자의 bool타입 연산 (0) | 2023.03.20 |
[TIL] 230317 협업을 위한 가상환경 설정법( venv 관리) (0) | 2023.03.19 |