import antigravity 를치면, 아래와 같은 그림이 나옵니다
http://xkcd.com/353/
Why Python? 이라는 물음에 대한 답입니다.
2011년 11월 19일 토요일
파이썬 List comprehension
파이썬의 List comprehension은 이걸 또 한글로 번역하면 말이 이상해지기때문에,
그냥 이대로 쓰겠습니다.
파이썬의 고차언어의 특징인 lambda , filter, map, reduce 알고리즘을 리스트로 간단히 구현하는 방법입니다.
보통 람다식을 써서,
a = [1,2,3,4,5] 이중에서 홀수만 골라낸다고 할때
filter (lambda x : x % 2 , a)
이런식으로 씁니다.
또, [1,2,3,4,5]의 리스트를 [2,4,6,8,10]으로 바꾸려면, 다음과 같이 합니다.
map(lambda x : x*2, a) 이런식으로 써줍니다.
그러면 list comprehension은 모냐, 똑같습니다.
[x for x in a if x % 2]
--> [1,3,5] 홀수만 골라내고,
[x*2 for x in a ]
--> [2,4,6,8,10] 두배로 튀겨줍니다.
그러면 람다식으로 하는거랑 리스트 컴프리헨션이 뭐가 다른가 하면,
다른거 없습니다. 똑같습니다.
결과도 똑같고, 사용문법만 조금 다른데,
뭐가 다른가하면 그냥 취향차이입니다.
커뮤니티에서는 그나마 list comprehension이 readable하다는 이유로 , list comprehension을 추천합니다.
이것을 일반적인 형태로 쓰면 아래와 같은데,
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN]
람다식으로 쓰면 훨씬 지저분해지겠죠, 괄호에 괄호가 중첩되는 형태이니,
이 리스트 컴프리헨션식은 for문을 중첩하는 것과 똑같습니다.
그럼 다시, for문이 낫냐, list 컴프리헨션이 낫냐의 문제로 돌아가면,
for문은 C언어부터 자바는 물론 현재도 많이 쓰는 방식이죠,,,
이것의 문제는 문제에 집중할 수 없는게 문제입니다.
if와 for문이 중첩되게 되면, 어디서 부터 끊어야 되는지,
또 차후에 코드를 다시 리뷰할때 이해가 쉽지 않습니다.
그리고, 정말 문제보다 바운더리컨디션에 신경을 많이 써야 됩니다.
그러다보니 그에 대한 반발로 function형 언어들이 나오게 된것이고
이러한 function형 언어는 , 익숙해지면, 정말 좋은 방법중의 하나입니다.
간단한 for문 if문 은 list comprehension으로 하면 됩니다.
남들 열줄쓸거 한두줄로 끝낼 수 있는거죠, 차후에 리뷰도 쉽고요,
C언어계열에서는 잘안쓰는 형태인데, 익숙해지면 정말 좋습니다.
그냥 이대로 쓰겠습니다.
파이썬의 고차언어의 특징인 lambda , filter, map, reduce 알고리즘을 리스트로 간단히 구현하는 방법입니다.
보통 람다식을 써서,
a = [1,2,3,4,5] 이중에서 홀수만 골라낸다고 할때
filter (lambda x : x % 2 , a)
이런식으로 씁니다.
또, [1,2,3,4,5]의 리스트를 [2,4,6,8,10]으로 바꾸려면, 다음과 같이 합니다.
map(lambda x : x*2, a) 이런식으로 써줍니다.
그러면 list comprehension은 모냐, 똑같습니다.
[x for x in a if x % 2]
--> [1,3,5] 홀수만 골라내고,
[x*2 for x in a ]
--> [2,4,6,8,10] 두배로 튀겨줍니다.
그러면 람다식으로 하는거랑 리스트 컴프리헨션이 뭐가 다른가 하면,
다른거 없습니다. 똑같습니다.
결과도 똑같고, 사용문법만 조금 다른데,
뭐가 다른가하면 그냥 취향차이입니다.
커뮤니티에서는 그나마 list comprehension이 readable하다는 이유로 , list comprehension을 추천합니다.
이것을 일반적인 형태로 쓰면 아래와 같은데,
[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN]
람다식으로 쓰면 훨씬 지저분해지겠죠, 괄호에 괄호가 중첩되는 형태이니,
이 리스트 컴프리헨션식은 for문을 중첩하는 것과 똑같습니다.
그럼 다시, for문이 낫냐, list 컴프리헨션이 낫냐의 문제로 돌아가면,
for문은 C언어부터 자바는 물론 현재도 많이 쓰는 방식이죠,,,
이것의 문제는 문제에 집중할 수 없는게 문제입니다.
if와 for문이 중첩되게 되면, 어디서 부터 끊어야 되는지,
또 차후에 코드를 다시 리뷰할때 이해가 쉽지 않습니다.
그리고, 정말 문제보다 바운더리컨디션에 신경을 많이 써야 됩니다.
그러다보니 그에 대한 반발로 function형 언어들이 나오게 된것이고
이러한 function형 언어는 , 익숙해지면, 정말 좋은 방법중의 하나입니다.
간단한 for문 if문 은 list comprehension으로 하면 됩니다.
남들 열줄쓸거 한두줄로 끝낼 수 있는거죠, 차후에 리뷰도 쉽고요,
C언어계열에서는 잘안쓰는 형태인데, 익숙해지면 정말 좋습니다.
2011년 11월 13일 일요일
파이썬 스레드 threading GIL
파이썬에서는 특이한 GIL이라는게 있습니다.
GIL이란 무엇이냐 하면 Global Interpreter Lock의 약자로 하나의 파이썬 인터프리터에서는 하나의 작업만 실행이 가능한 것입니다. 음 왜냐하면, 하나의 인터프리터가 실행이 될때, global 변수로 제어를 하기때문에, 여러 스레드가 동시에 건드릴 경우, 뒤죽박죽이 되기에, 한번에 하나의 스레드만이 인터프리터 내부 global 변수에 접근가능하도록 해놓은것입니다.
이것이 무슨일을 벌이느냐 하면, 멀티 스레드 프로그램을 짰을 경우 다른 스레드로 들어가기전에 락을 걸어놓고 움직입니다. 그래서,멀티스레드라 할지라도 결국에는
한번에 하나의 스레드가 time sharing하는 형태로 실행이 됩니다.
그래서 결과적으로 멀티코어 CPU라고 하더라도, 스레드를 사용할 경우 그다지 효과가 없고, 오히려 실행시간이 늘어나게 됩니다. 멀티스레드 모듈이 존재하긴 하는데,
이것이 그다지 효과가 없습니다. 그냥 시분할로 돌리는것과 성능이 비슷합니다.
이것이 효과를 보는 경우는 I/O같이 시간을 많이 잡아먹는 경우에는 효과가 있습니다.
I/O 타임에는 CPU가 놀고 있기때문에, 이때는 효과적이지만,
하이퍼스레딩이나, SMT같이 CPU 코어한개안에서 여럿의 프로세스들 돌리는 형태로는
효과를 많이 보지 못합니다.
예를 들면 1부터 200까지 더하는 프로그램을 짠다고 할 경우
1. 하나의 스레드는 처음부터 끝까지 진행
2. 두개의 스레드로 나눠서 하나는 1부터 100까지 더하게 하고,
다른 하나는 101부터 200까지 더하게 해서 합하는 경우
1번이 무조건 빠르게 됩니다.
2번의 경우 multithread를 쓴다면 효과가 있어야 되는데, 이 GIL때문에 하나의 cpu만을 가지고 진행하기때문에 중간에 Lock을 걸고 풀고하는 비용이 추가가 되어서, 2번이 1번보다 항상 느리게 됩니다.
그래서 이에 대한 해결 방법으로는 multiprocess를 쓰는 방법입니다.
즉, 하나의 interpreter를 쓰는게 아니라 여럿의 프로세서를 구동시키는 것이죠,
이 경우에는 프로세스 관리는 python에서 하는 것이 아니라 os에서 하는 것이기 때문에,
OS에서 적절하게 프로세스를 코어별로 할당을 하게 해서, 전체적으로 스피드를 올려주게 됩니다.
그럼에도 불구하고, 사실 멀티프로세서도 좋은 모델이긴하지만,
아쉬움이 많이 있습니다.
멀티프로세서와 하이퍼 스레딩같이 풀파워로 돌리기는 어렵고,
멀티프로세서를 극대화시키고,
적절하게 I/O bound 한 부분과 CPU bound한 부분을 나누는 것이 중요합니다.
또, 다른 방법은 GIL이 없는 구현, 예를들면, Jython 이나 IronPython을 이용하는 방법도 있긴합니다. https://wiki.python.org/moin/GlobalInterpreterLock
하지만, 일반적인 job을 하는 경우는 사실 이 상황을 맞닥드리긴 힘듭니다.
파이썬같은 경우는 주로 prototype 에서 가장좋은 효율을 보이기때문에,
이렇게 GIL에 장벽에 가로막히는 일까지 가는 경우가 그렇게 잘 발생하지는 않습니다.
CPU의 모든 성능을 끌어내는 경우는 보통 어떤 일이 완료된다음에 최적화수순을 밟는 경우라서,
이때는 bottleneck을 C로짜는 경우도 있고,
중요한 시스템은 C나 자바로 돌리는게 아직까지는 현실이기때문입니다.
이것 자체는 사실 좋은 주제이기때문에, GIL을 무력화시키려는 시도는 여럿있어 왔습니다만
여러가지 문제가 있어서, 아직까지는 GIL을 유지하는 것으로 가고 있습니다.
GIL이란 무엇이냐 하면 Global Interpreter Lock의 약자로 하나의 파이썬 인터프리터에서는 하나의 작업만 실행이 가능한 것입니다. 음 왜냐하면, 하나의 인터프리터가 실행이 될때, global 변수로 제어를 하기때문에, 여러 스레드가 동시에 건드릴 경우, 뒤죽박죽이 되기에, 한번에 하나의 스레드만이 인터프리터 내부 global 변수에 접근가능하도록 해놓은것입니다.
이것이 무슨일을 벌이느냐 하면, 멀티 스레드 프로그램을 짰을 경우 다른 스레드로 들어가기전에 락을 걸어놓고 움직입니다. 그래서,멀티스레드라 할지라도 결국에는
한번에 하나의 스레드가 time sharing하는 형태로 실행이 됩니다.
그래서 결과적으로 멀티코어 CPU라고 하더라도, 스레드를 사용할 경우 그다지 효과가 없고, 오히려 실행시간이 늘어나게 됩니다. 멀티스레드 모듈이 존재하긴 하는데,
이것이 그다지 효과가 없습니다. 그냥 시분할로 돌리는것과 성능이 비슷합니다.
이것이 효과를 보는 경우는 I/O같이 시간을 많이 잡아먹는 경우에는 효과가 있습니다.
I/O 타임에는 CPU가 놀고 있기때문에, 이때는 효과적이지만,
하이퍼스레딩이나, SMT같이 CPU 코어한개안에서 여럿의 프로세스들 돌리는 형태로는
효과를 많이 보지 못합니다.
예를 들면 1부터 200까지 더하는 프로그램을 짠다고 할 경우
1. 하나의 스레드는 처음부터 끝까지 진행
2. 두개의 스레드로 나눠서 하나는 1부터 100까지 더하게 하고,
다른 하나는 101부터 200까지 더하게 해서 합하는 경우
1번이 무조건 빠르게 됩니다.
2번의 경우 multithread를 쓴다면 효과가 있어야 되는데, 이 GIL때문에 하나의 cpu만을 가지고 진행하기때문에 중간에 Lock을 걸고 풀고하는 비용이 추가가 되어서, 2번이 1번보다 항상 느리게 됩니다.
그래서 이에 대한 해결 방법으로는 multiprocess를 쓰는 방법입니다.
즉, 하나의 interpreter를 쓰는게 아니라 여럿의 프로세서를 구동시키는 것이죠,
이 경우에는 프로세스 관리는 python에서 하는 것이 아니라 os에서 하는 것이기 때문에,
OS에서 적절하게 프로세스를 코어별로 할당을 하게 해서, 전체적으로 스피드를 올려주게 됩니다.
그럼에도 불구하고, 사실 멀티프로세서도 좋은 모델이긴하지만,
아쉬움이 많이 있습니다.
멀티프로세서와 하이퍼 스레딩같이 풀파워로 돌리기는 어렵고,
멀티프로세서를 극대화시키고,
적절하게 I/O bound 한 부분과 CPU bound한 부분을 나누는 것이 중요합니다.
또, 다른 방법은 GIL이 없는 구현, 예를들면, Jython 이나 IronPython을 이용하는 방법도 있긴합니다. https://wiki.python.org/moin/GlobalInterpreterLock
하지만, 일반적인 job을 하는 경우는 사실 이 상황을 맞닥드리긴 힘듭니다.
파이썬같은 경우는 주로 prototype 에서 가장좋은 효율을 보이기때문에,
이렇게 GIL에 장벽에 가로막히는 일까지 가는 경우가 그렇게 잘 발생하지는 않습니다.
이때는 bottleneck을 C로짜는 경우도 있고,
중요한 시스템은 C나 자바로 돌리는게 아직까지는 현실이기때문입니다.
이것 자체는 사실 좋은 주제이기때문에, GIL을 무력화시키려는 시도는 여럿있어 왔습니다만
여러가지 문제가 있어서, 아직까지는 GIL을 유지하는 것으로 가고 있습니다.
2011년 11월 10일 목요일
파이썬 pydev / eclipse 를 이용한 디버깅하기
이번글은 파이썬에서 이클립스를 이용해서 디버깅하는 것을 소개해드리려고 합니다.
원래 python용 debug는 pdb라고 있는데, 이것의 사용법이 gdb를 쓰는 수준이어서,
이것보다는 이클립스에서 사용하는게 좀더 편하기 때문에 이클립스를 기준으로 설명 드리도록 하겠습니다.
여기서는 pydev를 까는거는 pass하도록 하겠습니다. 찾아보시면 간단합니다.
일단 그림을 보시면 아주 간단한 합니다.
적당한 breakpoint를 잡을 수 있게 특정라인에서 더블클릭을 합니다.
그러면 녹색 체크 동그라미가 생기고,
여기서 F11을 이용해서 Debug run을 실행시키면 됩니다.
그게 디버깅을 하기 위한 준비입니다.
그리고나면 Perspective라는 창으로 들어가는데,
아래와 같습니다. 오른쪽 상당에 있는 Pydev와 Debug로 모드를 전환하게되고
Pydev를 누르면 위의 에디터 화면이 나오고, Debug를 누르면 아래와 같은 Perspective화면이 나옵니다.
그리고 Debug는 MS Visual studio랑 비슷합니다. F5-F8을 이용해서,
Step into 부터, 디버깅을 할 수 가 있고요, 오른쪽에 실시간으로, variables가 나옵니다.
일단 이렇게 pydev를 이용해서 debug를 하시면 되고,
실제로는 방법론적으로 breaking point를 잡아서 디버깅하는것도 하나의 방법이지만,
그냥 print 를 찍어서 하는게 더 빠를 경우도 있습니다.
복잡한 프로그램이라면, pydev의 debug를 이용하는게 더 좋을 수도 있고요,
간단한 프로그램이라면, 저런방법 보다도 간단히 log를 찍어서 확인하는 방법이
더 좋을 수도 있습니다.
예를 들면 실시간 환경에서는 저런식의 step debug가 불가능한경우도 있기때문에ㅡ
즉, 디버거의 성능때문이 아니라 어플리케이션의 성질에 따라서, 불가한 경우도 있기때문에,
log를 이용한 방법도 놓치지 않으셨으면 합니다.
또, eclipse를 사용한 방법은 편하긴하지만, 또 보다보면, pdb만 쓰는 환경이 있을 수도 있거든요, 그러니 어느 하나 소홀히 하지말고 쓰시다 보면 좋을 결과가 있을거 같습니다.
이상입니다.
피드 구독하기:
글 (Atom)