티스토리 뷰

안녕하세요.
파이썬이란 언어는 배우기 쉽고 코드 짜는 게 간단하며, 개발하기에 너무나 편한 언어입니다. 하지만 너무나도 느린 성능 때문에 개발자들의 항상 발목을 잡기도 합니다.
이 글은 파이썬의 느린 성능을 해결해주는 방법을 알아볼 것입니다.
 
먼저 파이썬이 C언어 보다 얼마나 느린지 알아보기 위해 실험을 해보겠습니다.

import time

cnt = 0
start = time.time()

for i in range(int(1e8)):
    cnt += i

print(time.time() - start)

위 두 개의 코드는 순서대로 C로 작성한 0부터 1억 미만까지 모든 수를 더할때의더할 때의 시간을 출력하는 프로그램, 파이썬으로 작성한 1부터 1억 미만까지 모든 수를 더할 때의 시간을 출력하는 프로그램입니다.
 
두 프로그램을 실행시킨 결과물은 아래 이미지와 같습니다.
 

C언어로 작성한 프로그램
파이썬으로 작성한 프로그램

확실히 파이썬이 느리죠? 이러한 연산을 파이썬에서 수행 시키려고하면 시간을 엄청나게 오래 걸리게 될 것입니다.
그렇다면 파이썬의 장점과 C언어의 장점을 두 가지 모두 동시에 얻을 수 있다면 어떨까요?
그러려면 파이썬의 Ctypes라는 모듈을 사용해야 합니다. 그전에 gcc 컴파일러를 설치해야 합니다.
gcc 컴파일러 설치에 관한 내용은 이미 블로그에 나와있는 자료들이 많기 때문에 이 글에서 따로 다루진 않겠습니다.
 
먼저 아래 이미지와 같이 새로운 폴더를 만들어주고 그 폴더 안에 test.py test.c 파일을 두 개 만들어 주세요.

test.c 파일에 아래와 같이 피보나치 수를 구하는 재귀 함수만 입력해줍니다.

int fibo(int n)
{
    if (n == 0)
        return 0;
    else if (n == 1)
        return 1;
    else
        return fibo(n-1) + fibo(n-2);
}

그리고 이 자리에서 CMD 창을 띄워 'gcc -c test.c' 라고 입력해줍니다. 그렇다면 아래 이미지와 같이 test.o 라는 오브젝트 파일이 만들어지게 됩니다.

오브젝트 파일(test.o)이 만들어졌다.

이번에는 다시 CMD 창에서 'gcc -shared -o test.dll test.o' 라고 입력해줍니다. 그렇다면 아래 이미지와 같이 test.dll 라는 라이브러리 파일이 만들어지게 됩니다.

다이나믹 링크 라이브러리 파일(test.dll)이 만들어졌다.

이제 C로 작성된 라이브러리 파일이 준비되었으니 파이썬에서 이 파일을 사용해보겠습니다. ctypes 라는 모듈은 파이썬용 외부 함수 라이브러리로 C호환 데이터형을 제공하며, DLL 또는 공유 라이브러리에 있는 함수를 호출할 수 있습니다.
 
test.py 파일을 아래와 같이 작성합니다.

from ctypes import cdll
test = cdll.LoadLibrary('test.dll')

print(test.fibo(40))

이를 실행시킨다면 다른 오류 없이 작동하는 모습을 확인할 수 있습니다. 그렇다면 파이썬으로 작성한 피보나치 재귀 함수와 어느 정도로 차이가 있을까요?
파이썬으로 피보나치 재귀 함수를 작성해보고 이것이 방금 작성한 코드와 성능 차이가 확연하게 나는지 테스트해보도록 하겠습니다.
 
test.py 파일을 아래와 같이 수정합니다.

from ctypes import cdll
test = cdll.LoadLibrary('test.dll')

def fibo(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibo(n-1) + fibo(n-2)

# print(test.fibo(40))
print(fibo(40))

이를 다시 실행시킨다면 잘 작동하겠지만, 아까 작성했던 코드와 실행 속도가 확연하게 차이가 날 것입니다.
time 모듈을 사용하여 이 두 개의 함수의 실행 속도가 어느 정도인지 알아보도록 하겠습니다.
 
test.py 파일을 아래와 같이 다시 수정합니다.

from ctypes import cdll
import time
test = cdll.LoadLibrary('test.dll')

def fibo(n):
    if n == 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibo(n-1) + fibo(n-2)

# C로 작성한 함수
start_1 = time.time()
test.fibo(35)
print(f"C : {time.time() - start_1}")

# 파이썬으로 작성한 함수
start_2 = time.time()
fibo(35)
print(f"Python : {time.time() - start_2}")

이를 실행한 결과물은 아래 이미지와 같습니다.

확연하게 보이는 성능 차이
test.fibofibo
0.07s3.87s

두 결과물을 비교하자면 Python으로 구현된 fibonacci는 재귀로 35번 실행되는데 약 3.87초가 걸리는 반면, C언어로 구현된 test.fibonacci는 약 0.07초로 약 55배나 빠르게 동작하는 것을 확인할 수 있습니다.
 
이번 실험을 통해 파이썬 코드 내에서 C언어로 작성된 함수를 사용할 수 있다는 점과 파이썬 코드를 C언어로 작성해 사용하면 연산 성능이 개선되는 것을 확인했습니다.
주의해야 할 점은, 연산 집약적인 코드에 한해 성능이 개선되는 것이며 동적 라이브러리 함수 호출을 남용하게 된다면 호출 과정에서 생기는 딜레이로 인해 오히려 성능이 떨어질 수 있음을 알아야 합니다.
 

P.S)

여담이지만 pypy로 컴파일을 한다면 빠른 성능을 체감하실 수 있습니다.
다음은 pypy에 대해 알아보는 글을 작성해보겠습니다.
 
감사합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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 31
글 보관함