Python과 Perl의 속도

차리서의 이미지

얼마전에 종강한 오토마타이론 강좌 막판에 간단한 프로그래밍 숙제가 있었습니다. 정해진 형식으로 표현된 임의의 DFA를 입력받아서 최소화시키는 프로그램을 작성하는 문제였는데, 채점하면서 여러가지 이야기거리가 생기더군요. 이 중에서 다른 이야기는 다른 글타래에 따로 쓰기로 하고, 이 자리에서는 Python과 Perl의 충격적인 비교 사례를 하나 이야기해볼까 합니다. 혹시 제가 뭔가를 잘못 알아서이거나 혹은 지극히 당연한 이야기일지도 모르지만, 어쨌든 제게는 무척 쇼킹한 사건이었습니다. (절대로 비건설적인 플레임을 유도할 생각은 없습니다.)

숙제의 명세 중에 비록 낮은 배점이긴 했지만 ‘수행 속도 측정’에 대한 부분이 들어있었습니다. 입력 자료 처리와 분석, 검증, 출력 등을 포함하는 전체 프로그램의 수행 속도를 재는건 아니었고, 순수하게 minimization 알고리즘만의 수행 속도를 재는 것이었습니다. (공학적 마인드로 무장한 실전 프로그래밍 강좌가 아니라 논리적 마인드를 요구하는 오토마타‘이론’ 강좌였으니까요. 즉, 속도에 대한 요구는 그저 ‘덤’ 정도였을 뿐이죠.) 구현 언어에 제한을 두지 않았던지라 비교 평가는 같은 언어끼리만 하기로 했었습니다만, 비교를 안 할래야 안 할 수 없는 일이 벌어지고 말았습니다.

저는 구현 언어로 Python을 선택했습니다. 선택하던 순간부터 이미 속도 문제는 신경쓰지 않기로 마음먹은 것이었고, 채점 기준 상 어차피 같은 언어끼리만 속도를 비교하여 평가한다는 사실도 크게 작용했습니다. 어디까지나 ‘가능한 한 적은 작업량으로 빠르고 편하게 숙제를 해치우는’ 데에 포인트를 둔 선택이었죠. 결과적으로 수강생 30여명 중에서 Python으로 제출한 사람은 저뿐이었고 Perl로 작성해서 제출한 사람 또한 한 사람 뿐이었습니다. 물론 Python과 Perl은 서로 다른 언어이므로 공식적으로 비교 대상이 되지는 않았지만, 둘 다 (제가 알기로는) 런타임 인터프리터에 의존하는 스크립트 언어고, 실제로 이 언어들이 지향하는 타겟 영역에도 상당히 큰 교집합이 있으므로, 상식적으로라면 이들 간의 속도 차이도 어느 정도 일리있는 범위 내에 있어야 정상이라고 믿었습니다. 어떤 작업을 어떤 방식으로 수행하는 경우냐에 따라 속도 차이라는 것도 얼마든지 뒤집히거나 더 벌어질 수 있겠지만, 그래도 역시 상식적인 범위 내에서 왔다갔다하리라 믿었습니다. 하지만...

약 7000배! :shock:

Perl은 의외로 빠른 언어라고들 합니다. Python이 꽤 무거운 언어라는 지적도 여기저기에서 본 것 같습니다. 예. 알고 있었습니다. 같은 스크립트 언어라고 해도 분명히 Perl이 Python보다 빠르리라는 정도는 저도 대충 예상하고 있었습니다. 알고 있다고 믿었죠. 그런데.... 7000배라니요!!!! 300개의 상태들과 세 개의 입력 문자를 갖고, unreachable states가 약 60개 정도이며, 이런 unreachable states들만 파악해서 떼어내면 더이상 동치인 상태 쌍이 없는 DFA를 입력했을 때, 제 Python 스크립트가 약 5분 30여초에 걸쳐 계산하는 반면 Perl 스크립트는 48 밀리초에 끝내더군요.

물론 제 Python 프로그램도 제 능력으로 할 수 있는 한 최선을 다해서 속도를 위한 최적화를 해 두었습니다. 심지어 애초에 Python을 선택하던 당시의 의도와는 달리 대부분의 ‘Python 다움’마저 포기하면서까지 말이죠. DFA 최소화 알고리즘 자체도 (가장 덜 엘레강스하고 구현하기 귀찮음에도 불구하고) 가장 효율적인 녀석을 선택했습니다. 그나마 재귀적으로 표현된 알고리즘을 당연히 iteration으로 완전히 풀어버렸고, 루프 속에서는 Python 내부적으로 비싼 일이 벌어질지 모르는 모든 경우를 배제했다고 생각합니다.

혹시 Perl로 제출된 프로그램은 뭔가 기똥찬 선형 알고리즘을 쓰고있나 싶어서 (Perl을 전혀 모름에도 불구하고) 열심히 들여다보았으나, 루프 구조와 각 장소의 변수명 등으로 볼 때 분명히 저와 거의 똑같은 작업을 똑같은 절차로 수행하고 있었습니다. 게다가, 예를들어 list의 메모리 동적 할당처럼, 제가 Python 코드를 작성하면서 그렇게 조심스러웠던 비싼 자료구조까지도 Perl 코드에서는 아낌없이 쓰고 있는 듯이 보였습니다.

유일하게 한 가지 의심스러운 부분이 있다면, 개념대로 편안하게 코딩하고자 하는 욕심에 DFA class를 만들고 minimization 함수를 DFA 클래스의 메서드로 구현했다는 점 뿐입니다. 결국 끝까지 포기하지 못한 Python스러움의 한가지이긴 한데, 설마 이게 그렇게 큰 죄였을까요? :cry:

기왕에 수강한 강좌에서 (덤으로나마) 공학적 시점에서의 효율을 요구했으니 잠시 고민해봤던 것일 뿐, 제 연구 분야의 성격 상 앞으로는 (아마도 평생) 이런 류의 효율 문제와 싸울 일이 없을거고 (간단히 말하자면 기나 아니냐의 문제일 뿐이거든요) 저 자신도 별로 관심 없이 지내던 영역입니다만, 역시 아무래도 저같은 사람이야말로 조엘이 말하는 문제아인가봅니다. 제가 선택한 분야의 연구를 평생 하겠노라고 결심한 이상, 중간에 잠시라도 실전 (field) 개발 현장에 취직해서 월급받을 생각은 싹 버려야겠습니다. 순수하게 이론에 투자하는 연구소가 아닌 이상 저같은 사람을 고용하려는 곳도 웬만해서는 없겠지만 말이죠. ^^;;

PS: 변명같기는 하지만, 아무리 생각해봐도 7000배라는 극단적인 차이가 ‘제가 Python 코드를 멍청하게 짰기 때문’은 아닌 것 같습니다. 오히려 Perl 프로그램 쪽이 도저히 믿을 수 없을 만큼 너무나 빠른 속도로 동작하고 있다는 생각이 듭니다. 왜냐하면, 위에서 말한 예제 DFA에 대한 Perl 프로그램의 처리 속도인 48 밀리초는 C로 구현한 코드를 컴파일해서 실행했을 때의 속도와 거의 차이가 없는 (기껏해야 10배 남짓) 경이로운 속도거든요. :shock:

File attachments: 
첨부파일 크기
PDF icon hwquest-minimization.pdf279.5 KB
Binary Data common_inputs.tar.gz109.6 KB
Binary Data script.tar.gz4.71 KB
galien의 이미지

0_0);;;;

정말 쇼킹하군요. 파이썬 좀 더 익숙해지면 (아직 인터프리터 언어, 스크립트 언어,
문자 다루는 데 강한 언어 류 에 익숙하지 않아서), 펄을 꼭 해야 하는 건가용...

그 외의 다른 비교 예를 아시는 분 있으면, 혹은 펄의 geek 스러운 측면 외의
장점을 소개하실 분 답글들 좀 부탁드립니다.

aero의 이미지

김상욱 wrote:
0_0);;;;

정말 쇼킹하군요. 파이썬 좀 더 익숙해지면 (아직 인터프리터 언어, 스크립트 언어,
문자 다루는 데 강한 언어 류 에 익숙하지 않아서), 펄을 꼭 해야 하는 건가용...

그 외의 다른 비교 예를 아시는 분 있으면, 혹은 펄의 geek 스러운 측면 외의
장점을 소개하실 분 답글들 좀 부탁드립니다.

뭐 위의 경우는 특수한 경우인지 모르지만 실제로 여러벤치마크 결과를 보면 perl이랑 python의 성능은 그렇게 많이 차이는 나지 않는걸로
알고 있습니다. 서로 더 우수한 부분도 있고.

언어야 자기에게 맞는걸 쓰면 되겠지만.

두언어는 언어구조상의 차이점도 있지만 사용자 커뮤니티의 분위기와
철학이랄까 그런것에도 확실히 달라 보이는 점이 있습니다.

저는 항상 그런생각을 합니다. Perl의 낙타와 Python의 비단뱀이
어떻게 해당언어 사용자커뮤니티의 분위기와 속성이랑 그렇게
맞아 들어가는지 :)

doldori의 이미지

이것은 펄과 파이썬의 비교가 아니라 펄의 어떤 구현체와 파이썬의 어떤 구현체를
비교한 것이로군요. 혹시 다른 구현체로도 시험을 해보실 생각은 없으신가요?

acidd15의 이미지

흠...

hys545의 이미지

특정 알고리즘만 가지고 속도 따진다면
문제가 있습니다.
언어마다 특성이 다르기 때문에 특정 알고리즘에서 더 빠를수도 있습니다.

즐린

galien의 이미지

aero wrote:
두언어는 언어구조상의 차이점도 있지만 사용자 커뮤니티의 분위기와
철학이랄까 그런것에도 확실히 달라 보이는 점이 있습니다.

저는 항상 그런생각을 합니다. Perl의 낙타와 Python의 비단뱀이
어떻게 해당언어 사용자커뮤니티의 분위기와 속성이랑 그렇게
맞아 들어가는지 :)

주관적으로 분위기가 어떻다고 판단이 되시는지 궁금합니다.

정확한 팩트를 부탁드리는 게 아니니깐 부담 갖지 마시고 편하게 표현해주시면
감사하겠습니다.

어떤 쪽이 저랑 더 맞을지 알고 싶어서요..

:lol:

코퍼스의 이미지

사실 각 언어마다 구현상의 차이점이 존재하고, 이에 따라 유사한 언어일 지라도 각 작업 영역마다 속도상의 차이라던가, 메모리 사용량에 차이를 보입니다.

이미 HMM(히든 마코브 모델)의 구현에서도 펄로 짜인 코드가 엄청난 속도를 보였습니다.(이때의 예에서는 오히려 C보다도 빨랐다고 하는군요)

많은 언어비교 실험에서 펄은 그 엄청난 실행속도를 자랑했었지요..

물론 특정 알고리즘 실험에서는 파이썬이 나은 시험도 있었으니.. 무조건 펄이 나은 성능을 보인 것은 아닙니다.

( 물론, 이 논의에서는 펄과 파이썬 언어가 가진 언어 자체의 우열성 비교는 아님을 잘 알고 있습니다. 그렇지만, 제가 원래 펄 예찬론자 쪽이므로,, 혹 제 글에 오해가 있을까하는 노파심에 글을 적는데요.
기타, 언어사용에 있어서는 여러가지 장점과 고려사항을 따져야 하므로 그런 경우에는 파이썬의 다른 장점들이 더 부각될 수 있음을 적습니다.^^)

A few Good Man

mithrandir의 이미지

실행 데이터가 궁금합니다 :-)

소스와 데이터를 공개해 주실 수 있나요?

언제나 삽질 - http://tisphie.net/typo/
프로그래밍 언어 개발 - http://langdev.net

sodomau의 이미지

언어마다 똑같은 알고리즘의
결과물의 실행시간이 다르다는 것이
그 언어의 특정한 언어적 특성과 특정 내부 모듈의
구현에서 차이가 나기 때문이겠죠?

이런 경우, 이렇게 심하게 차이가 난다면
도대체 구체적으로 어디서부터 그런 차이가 생기는 걸까요?
개인적으로 파이썬을 좋아하는데..
펄과 다른 어떤 점이 이런 어마어마한 속도 저하를 가져왔는지
궁금하군요.

차리서의 이미지

mithrandir wrote:
실행 데이터가 궁금합니다 :-)
소스와 데이터를 공개해 주실 수 있나요?

제 Python 소스를 공개하는 데에는 ‘무지하게 창피한 상황이 벌어질까봐 두렵다는’ 딱 한가지 문제 밖에 없으며, 눈만 딱 감으면 극복 가능합니다. :) (코드를 공개함으로써 제 코드에 뭔가 심각한 문제가 있었음을 발견할 수만 있다면 그까짓 창피함 쯤이야 싼 댓가죠.) 숙제의 프로그램 요구 명세서와 실행 데이터도 얼마든지 공개할 수 있습니다.

그러나, 다른 수강생의 과제 제출물인 Perl 코드는 절대로 제가 독단적으로 공개할 수 없습니다. 코드를 공개하고싶은 이유가 아무리 지금 이 경우처럼 ‘그것이 너무나 훌륭해서’라고 해도 말이죠. 특히 수업 조교 입장이었던 제 경우에는 이런 문제에 무척 조금스러워야한다고 생각합니다. 다만, 조만간 해당 Perl 코드의 작성자와 한 번 만나서 Python 프로그램과의 속도 차이에 대한 이야기를 나눠볼 생각인데, 이 때 코드 작성자 본인에게 코드 공개에 대해 ‘양해를 구해볼’ 수는 있을 것 같습니다. 만일 당사자가 공개를 허락해준다면 추후에 Perl 코드도 공개하겠습니다.

첨부하는 파일들은 프로그램 요구 명세서와 샘플 데이터들 (이 중에는 구문 오류나 의미 오류가 고의적으로 포함된 예제들도 있습니다), 그리고 (아직 Perl 코드를 공개하지 못하는 상황이라서 어차피 큰 의미는 없지만) 제 Python 스크립트입니다.

숙제 요구 명세서와 실제 숙제 사이에 한 가지 차이가 있습니다. 명세서 대로라면 프로그램은 물리적인 메모리나 OS가 제공해준 메모리가 허용하는 한 임의의 갯수의 상태들을 처리할 수 있어야합니다. (즉, 프로그램의 올바른 입력 DFA의 상태 수에는 상한선이 없어야한다는 얘기죠.) 그러나, 명세서가 공지된 후 강의시간에 교수님께서 구두로 이 부분을 ‘1000개까지만 처리하자’고 바꾸셨습니다.

샘플 입력 데이터들 중에는 숙제의 오류처리 평가를 위해 일부러 구문 오류나 (2번) 의미 오류를 (3번과 4번) 조작해넣은 예제도 있습니다. 1번 예제는 예쁘게 최소화되는 작은 예제이고, 5번과 7번은 전혀 최소화가 안되는 예제입니다. 6번은 unreachable states만 떼어내고 나면 나머지 상태들은 더이상 축약되지 않는 예제입니다.

제 Python 스크립트 중에서 automata.py는 DFA 클래스를 구현해둔 라이브러리고, dfaminimize가 최소화 프로그램 본체입니다. 이들은 같은 디렉토리에 들어있어야합니다. 나머지 스크립트들은 샘플 생성과 숙제 채점 등 조교로서의 업무를 위해 급히 제작한 떨거지 프로그램들이며, 일부 요소가 제대로 동작하지 않는 것도 섞여있을 수 있습니다.

댓글 첨부 파일: 
첨부파일 크기
PDF icon 0바이트
Binary Data 0바이트
Binary Data 0바이트

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

차리서의 이미지

sodomau wrote:
이런 경우, 이렇게 심하게 차이가 난다면
도대체 구체적으로 어디서부터 그런 차이가 생기는 걸까요?
개인적으로 파이썬을 좋아하는데..
펄과 다른 어떤 점이 이런 어마어마한 속도 저하를 가져왔는지
궁금하군요.

저도 바로 이 부분이 무척 궁금합니다만,
  • 어쩌면 완전이 똑같은 알고리즘이 아니었을 수도 있고 (제가 Perl을 몰라서 잘못 보았을 수도 있습니다.)
  • 상당히 적지 않은 가능성으로, 제가 Python 코드를 몹시 멍청댕구리하게 만들어기 때문일 수도 있습니다.
특히 후자가 원인이라면 매우 부끄러운 일이겠지만, 그래도 또 한편으로는 후자가 원인이었다는 것을 알게되었다는 사실만으로도 역시 기쁠 것 같습니다. :)[/]

--
자본주의, 자유민주주의 사회에서는 결국 자유마저 돈으로 사야하나보다.
사줄테니 제발 팔기나 해다오. 아직 내가 "사겠다"고 말하는 동안에 말이다!

saxboy의 이미지

오. 이건 완전히 별개의 이야기이지만, 정말 흔히 보기 힘든 제대로 된 숙제의 specification 이군요! 차리서님 대단하십니다. 와와... 박수, 짝짝짝.

1day1의 이미지

구체적으로 동일한 상황에서 perl 과 python 을 비교해보진 않았지만,
단순히 perl 이 빠르다는 느낌상으로 생각하고 있었습니다. 그렇지만, 7000배 정도로 차이가 나지는 않았던 것으로 생각이 됩니다.

ps. 그런데, 이 글은 자유게시판 보다 다른 곳에서 토론하는 것이 더 좋을 것 같네요.

F/OSS 가 함께하길..

7339989b62a014c4ce6e31b3540bc7b5f06455024f22753f6235c935e8e5의 이미지

파이썬 버전에 따라서도 실행 속도가 달라지지 않을까요?
파이썬 2.4에서는 속도 면에서도 많은 변화가 있다고 들었습니다.
OS에 따라서 속도가 다를 수도 있겠군요.

아... 그리고 처음 실행 시 (바이트코드가 없을 때), 두번째 실행 시 (바이트코드가 있을 때), -O 옵션 (최적화 옵션)을 줘서 실행했을 때에도 결과에 차이가 있지 않을까 합니다.
psyco를 사용해서 속도를 빠르게 하거나 pyrex를 이용해서 일부를 C로 확장하면 또다른 결과가 나오겠군요. :)

lifthrasiir의 이미지

ditto wrote:
파이썬 버전에 따라서도 실행 속도가 달라지지 않을까요?
파이썬 2.4에서는 속도 면에서도 많은 변화가 있다고 들었습니다.
OS에 따라서 속도가 다를 수도 있겠군요.

아... 그리고 처음 실행 시 (바이트코드가 없을 때), 두번째 실행 시 (바이트코드가 있을 때), -O 옵션 (최적화 옵션)을 줘서 실행했을 때에도 결과에 차이가 있지 않을까 합니다.
psyco를 사용해서 속도를 빠르게 하거나 pyrex를 이용해서 일부를 C로 확장하면 또다른 결과가 나오겠군요. :)

pyrex 쓰는 건 좀 반칙...이고 ㄱ- psyco를 쓰면 어떨까 싶네요.

- 토끼군

zzaratra의 이미지

패턴 매칭에서 속도 차이 아닐까 합니다..

python 의 re 말고 다른거 써 보는건 어떨지..

여튼 궁금.. 그냥...

혹시 관계 있나 싶어서

http://nixdoc.net/files/forum/about25816.html

아니면 말구 --;;