파이썬은 왜 느린가?

intro

  • “파이썬은 느리다”라고 많은 사람들이 알고 있습니다. 그런데, 이 지점에서 “파이썬이 왜 느린가요?”라고 물어보면 대부분 답변을 못합니다.
  • 답변을 한다면, “파이썬은 인터프리터언어 혹은 스크립트 언어라서 그렇다”라고 하고, 혹은 “동적타입언어기 때문이지”라고 하곤 합니다.
  • 여기까지 들으면 뭐 그럴 수 있겠다 싶은데, 문제는 여기서 한발 더 나아갈 때 발생합니다.
  • “동적타입언어면 왜 느린데?”, 혹은 “인터프리터어면 왜 느린데?”에서는 대부분 답을 하기 어려워 합니다.
  • 실제로 구글에서 “왜 파이썬은 느린가”등으로 검색을 해보면, “동적타입언어이기 때문”이라고는 답변이 있지만, “동적타입언어의 어떤 점이 속도를 느리게 하는지”에 대해서는 정확하게 작성된 글이 잘 없습니다.
  • 그래서 계속 찾던 중에 다음과 같은 포스트가 있어서 해당 포스트에 제 생각을 넣어서 정리해보았습니다. 본 포스트가 유용하다고 생각하셨다면, 그것은 모두 제가 링크한 포스트가 매우 유용했기 때문입니다.

why python is slow??

동적타입언어.

  • 해당 포스트에서는 정적 타입언어인 C와 동적 타입언어인 python을 비교해서 설명하고 있습니다.
  • C의 경우 다음과 같은 코드를 가지게 됩니다.
    • 코딩 단계에서 각 변수의 타입을 설정했고, 변수의 합으로 인해 생성될 새로운 타입까지도 설정되어 있습니다.
    • 그리고 연산인 +에 대해서도 input은 어떤 type이고 output이 어떤 타입인지에 대해서 바로 알 수 있습니다. 이미 모든 변수의 타입이 정의되어 있으니까요.
    • 따라서 각 타입에 적절한 연산 함수 그리고 연산의 결과로 발생할 결과를 저장할 타입도 무엇인지에 대해서 컴파일단계에서 이미 다 알수 있다는 것이죠.
int a = 1; 
int b = 2;
int c = a+b;
  • 그러나 python의 경우 다음과 같은 코드를 가집니다.
    • 사람의 경우, 슥 보면, a, b 모두 정수형이고, 따라서 c도 정수형이지, 그리고 연산은 정수+정수에 대해서 처리하는 함수를 가져오면 되는거 아니야? 라고 바로 생각할 수 있지만 컴퓨터는 모릅니다.
a = 1
b = 2
c = a+b
  • 아래의 코드와 위의 코드는 같은 방식으로 운영됩니다. 단 적용되는 연산 함수, +의 역할이 다를 뿐이죠.
  • 즉, 이렇게 각각의 타입이 명확하게 설정되어 있지 않을 경우에는 각 타입을 인지하고, 해당 타입에 적합한 연산을 찾고, 그 결과로 생성되는 결과의 변수를 이후에 할당해줘야 하는 등의 문제가 발생하기 때문에, 속도가 느려집니다.
    • 지금은 비교적 간단하지만, 훨씬 복잡하고 큰 코드라면 이 문제는 더 심각해지겠죠.
a = "1"
b = "2"
c = a+b

그외.

  • 제가 참고한 포스트에서는 그 외에도 다양한 문제점들을 몇 개 말하고 있습니다. 다만, 제 지식의 한계로 명확하게 정리가 어려운 점들을 몇 개 작성해둡니다.
    • 인터프리터 언어이기 때문에: 보통 사람들이 인터프리터 언어를 말할때 “동적타입언어”와 같은 의미로 말하곤 합니다. 따라서 이 부분은 현재로서는 앞에서 말한 부분과 겹칩니다. 그러나, 실제로 파이썬이 인터프리팅 => 컴파일 될때 어떤 변화가 발생하고, 따라서 더 느려질 수 밖에 없다 는 것은 “동적타입언어”의 타입추론, 함수 추론 이외에도 다양한 차이가 있을 것 같습니다.
      • 이 부분을 제가 정확하게 설명하기 위해서는 컴파일러에 대해서 명확하게 알아야 하는데 제가 몰라요ㅠㅠ다음에 알게 되면 새로운 포스트로 정리하겠습니다.
    • 메모리 접근 및 관리: 해당 포스트에서 작성한 그림에서 알 수 있는 것처럼, np.array의 경우 각 값을 c의 어레이처럼 연속된 메모리에 저장합니다. 따라서 순차적으로 값을 읽기가 훨씬 쉽죠. 그러나, 파이썬의 리스트는 포인터를 합친 것만 관리하고 나머지는 모두 따로따로 관리되어 있습니다. 즉 리스트에서 값을 읽고 그 다음 값을 읽을 때 다시 포인터를 통해서 메모리 주소로 접근하는 등의 부차적인 비용이 발생하는 것 같습니다.
      • 사실 이것은 np.array의 경우 해당 자료구조내에 있는 모든 값이 동일한 데이터 타입인 반면, list는 어떤 데이터 타입도 모두 넣을 수 있기 때문에 발생하는 것으로 여겨지기도 합니다.

outro

  • 아무튼, “동적타입언어는 해당 데이터의 타입을 몰라서, 적절한 타입을 찾고, 그 타입들의 연산을 지원하는 함수를 또 찾아야 하고 하는 등의 부차적인 비용이 발생하기 때문에 시간이 더 오래 걸린다”라고 말할 수 있겠네요. 허허

reference

댓글남기기