태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

'Tech'에 해당되는 글 55건

  1. 2012.08.23 Amazon glacier ... 를 쓸 뻔 했던 이야기
  2. 2012.08.10 회사일 하면서 삽질하거나 느낀거 끄적 (2)
  3. 2011.07.12 D2, array.reverse property has a side-effect. orz (45)
  4. 2011.05.15 Thrift in D (6)
  5. 2010.12.12 fix: ugly gitweb page (3)
  6. 2010.08.08 (1/2) Programming in clojure (4)
  7. 2010.07.24 자바스크립트로 벽돌깨기를 만들어보고 싶은데 ... ... (5)
  8. 2010.05.16 Bit count with CUDA (T_T) (3)
  9. 2010.05.10 iterator invalidation (5)
  10. 2010.02.11 사용소감2: Google protocol buffer (1)
  11. 2010.02.04 사용소감: Google protocol buffer (4)
  12. 2009.12.29 TDD: 켄트백아저씨가 쓴 책이지? (2)
  13. 2009.12.17 git/git-svn on working machine (2)
  14. 2009.12.09 Links on xml and related techs (1)
  15. 2009.12.01 SICP 근황 (8)
  16. 2009.11.19 django 삽질 (3)
  17. 2009.09.17 CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty) (2)
  18. 2009.01.21 Parameter vs Argument (3)
  19. 2008.10.20 GEB: MU puzzle (4)
  20. 2008.09.26 MySQL -> XML: CDATA Sanitize? (2)
  21. 2008.09.11 하위 디렉토리에 있는 모든 .svn 을 날리는 법 (5)
  22. 2008.08.09 Spiral number galaxy (4)
  23. 2008.08.01 투명 필름 문제(Scheme) (4)
  24. 2008.07.22 Statement vs Expression (4)
  25. 2008.07.18 emacs: switch indentation
  26. 2008.06.11 방법당하다 by python-mysqldb 1.2.1_p2 (5)
  27. 2008.06.05 Troubleshooting: apt-get update -> Dynamic MMap out of room
  28. 2008.05.23 스팸폭탄 맞았음
  29. 2008.03.27 Chunker's rolling out! (3)
  30. 2008.03.20 Hadoop 0.15.2 -> 0.17.0 (4)

Amazon glacier ... 를 쓸 뻔 했던 이야기

Tech 2012.08.23 23:03

오늘은 평소에 삽질하던거랑 상관 없는 단독삽질. Amazon glacier를 써본다.

1. What is glacier?
아마존의 Archiving storage service. 저장 용량에 비해 매우 싼 대신, 트래픽 비용이 있고 꺼내오는 것도 실시간이 아니다.

참고자료:
http://www.zdnet.co.kr/news/news_view.asp?artice_id=20120822145556
http://aws.amazon.com/ko/glacier/

내가 개인 서버를 꾸려서 archive 디렉토리에 넣어둔 데이터가 대략 200G 정도 되는데, 이걸 glacier에 던져두고 싶다.
요금은 한달에 3천원 정도 예상한다. (미국 동부 0.01 USD/GB/MONTH 기준)

2. Create a vault
Amazon AWS 계정이 필요하다. 웹 콘솔에서 Services -> Glacier 를 클릭하면 결제정보가 없는 경우 payment method 를 확인한다고 뜨고, 결제 정보가 잘 들어가 있는 경우 Create vault 버튼이 덩그라니 보인다.
Vault 는 아카이브를 모으는 창고 같은 개념이다. 난 DGoonStorage 라는 이름의 vault 를 만들었다.
왼쪽 위 Region 에서 적절한 장소를 고르는걸 잊지 말자. 난 제일 싼 미국 동부(…)로 했다.
귀찮으니 Notification 설정 따위는 그냥 다 스킵.
Vault를 생성하고 나면 뭔가 보인다 …
하지만 여기서 바로 업로드를 할 수는 없다. Glacier는 콘솔에서 Vault생성/리스트업 이외의 작업이 불가하다.
파일을 업로드/다운로드하는 것 모두 "프로그래밍" 이 필요하다. 그게 내가 이런 쓰잘데기 없는 문서를 쓰는 이유이기도 하고…

3. Unit
Glacier에 저장되는 단위는 위에서 생성한 Vault, 그리고 Archive, 마지막으로 File 이 있다.

Archive는 하나 혹은 여러개의 File을 묶는 단위이다. Archive에는 Unique identifier가 발급되며 업로드/다운로드의 단위가 된다.
한 번의 업로드 요청으로 업로드 가능한 것은 4GB 까지. Archive 하나의 최대 용량은 40TB.
큰 Archive는 Multipart 요청으로 여러개의 조각으로 쪼개서 올려야 한다는 것.
그리고 Archive는 일단 정해지면 추가나 덮어쓰기가 불가하다. 삭제하고 다시 올리는 수 밖에 없다.
+ 올리고 3개월 이내, 혹은 업로드 중에 그만두고 삭제하면 '삭제비용'이 따로 든다!

Vault는 여러개의 Archive를 묶는 단위이다. Upto 1000 vaults per account per region 이라고 한다.
Archive가 하나도 없는 Vault만이 삭제가 가능하므로 Vault를 지우려면 안에 있는 Archive를 먼저 지워야 한다.

4. Amazon API
Python Boto 라는 훌륭한 라이브러리가 있다. 예전에 API 세팅할 때에는 자바로 삽질하느라 짜증났는데, 세상 좋아졌다.
하지만 Glacier는 비교적 최신에 릴리즈된 서비스라서 아직 boto 에 구현이 되어 있지 않다.

BOTO 관련 링크:
https://github.com/boto/boto
http://docs.pythonboto.org/en/latest/index.html

하지만 boto 베이스로 glacier upload/download 를 구현한 코드들이 gist 어딘가를 떠돌고 있으니(https://gist.github.com/3426839, https://gist.github.com/3424129), 조만간에 boto 에서 지원하리라 생각한다.
boto 설정을 위해서는 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 두 개가 필요하다. 이것은 웹 콘솔에서

Security credentials -> Access Keys

에서 보거나 생성할 수 있다. 이걸 boto 라이브러리에게 전달하는 방법은 설정파일, 환경변수, connect 할때 직접 등 여러가지가 있다.
나는 ~/.boto 파일에

[Credentials]
aws_access_key_id = <MY_ACCESS_KEY>
aws_secret_access_key = <MY_SECRET_KEY>

이렇게 적어넣는 방법을 사용했다. boto 라이브러리는 pip install boto 로 설치 가능하다.



나도 일단 boto 위에 만들어보려고 하는데, glacier api reference 찾는게 좀 어렵다. 검색해도 잘 안나오네. 검색해서 찾는데 30분이나 걸렸다.

Developer guide: http://docs.amazonwebservices.com/amazonglacier/latest/dev/
API Ref for glacier: http://docs.amazonwebservices.com/amazonglacier/latest/dev/amazon-glacier-api.html

금방 될 줄 알았는데, 일단 문서를 읽어봐야 할테니 시간 좀 걸리겠네 …
boto 에 추가될때까지 기다리는게 더 빠를지도!



5. Epilogue

잠시 검색 후: issue 를 보니,

https://github.com/boto/boto/issues/929
https://github.com/boto/boto/tree/glacier

이렇게 벌써 브랜치가 생겨있다. 빠르네 ㅋㅋㅋ

아, 회사 일 할게 많아서 오늘은 삽질을 별로 못했다. 남은 시간은 boto 라이브러리(와 glacier 브랜치) 코드나 읽으며 보내야겠다. boto는 회사일에도 유용할 듯. 자바 껒여.



'Tech' 카테고리의 다른 글

Amazon glacier ... 를 쓸 뻔 했던 이야기  (0) 2012.08.23
회사일 하면서 삽질하거나 느낀거 끄적  (2) 2012.08.10
D2, array.reverse property has a side-effect. orz  (45) 2011.07.12
Thrift in D  (6) 2011.05.15
fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
Trackbacks 0 : Comments 0

회사일 하면서 삽질하거나 느낀거 끄적

Tech 2012.08.10 13:54

요새 <종료되지 않고 계속 실행되며 모종의 일을 하거나, 서비스를 하는 프로세스> 들을 만들고 있다.

초보 프로그래머 디군은 참으로 많은 삽질을 하였는데, 실수를 다시 하지 않기 위해서 몇 가지 끄적여둔다.


1. 커널파라미터와 limits를 확인
/etc/security/limits.conf, /etc/sysctl.conf
특히 nofile 때문에 방법당하는 경우가 많다.

2. 리밋은 리밋일 뿐
  하드리밋이 풀려 있어도 돌고 있는 프로세스 자체에 적용된 값은 다를 수 있다.
  쉘에서 ulimit -a 로 확인했어도 프로세스 실행 계정이 다른 경우 쉘에서 보이는 것과 다른 값으로 뜰 수 있다.
  프로세스 자체적으로 getrlimit 으로 확인하고, setrlimit 으로 필요한 리소스를 확보해야 한다.
  필요한 만큼의 리소스를 얻지 못한다면 경고를 띄우거나 실행을 거부해도 좋아 …
  실행중인 프로세스의 정보는 cat /proc/[PID]/limits 로 볼 수 있다.

3. 타임아웃
  클라이언트에서 접속을 끊었어도 서버에서 callback 걸고 기다리는 중에 모를 수 있다.
실제로 오래 기다리는 경우도 발생하기 때문에 timed_async_read 에 타임아웃 5천초를 주었는데,
다른쪽 엔드포인트에서 접속 끊은걸 5천초동안 모르고 있는 상황이 발생 -> CLOSE_WAIT 가 쌓인다...
idle 대기일 때도 적절히 소켓 너머가 살아있는지 확인해줄 필요가 있다.
그 외에도 어디에서든 IO가 생기는 경우에 타임아웃 없이 기다리는 일은 절대 없도록 한다.

4. 설명 못하면 새는거야
코드에서 new/delete 만 모아놓고 살펴봐도 자명한 메모리 릭이 보이는 경우가 많다.
new/delete 뿐 아니라 모든 경우에 해당하는데, 할당된 자원이 언제 어떻게 해제되는지
빈틈없이 설명할 수 없다면 자원이 새거나 프로그래머의 정신이 새거나 둘 중 하나다. RAII.

5. 민폐 프로세스 방지
본인 코드의 메모리 사용에 대해 100% 확신하더라도, 프로세스 자체적으로 메모리 사용량을 주기적으로 확인해서
문제가 생긴다면 자살을 하거나 로그에 경고를 남기거나 등등 모종의 조치를 취할 필요가 있다.
사용중인 모든 라이브러리들이 메모리 누수가 없다고 자신할 수 있는가?
혼자 메모리 다 처묵처묵해서 머신 통째로 방법하는 일은 피하자.

6. 최적화?
O 올바르게 동작하는 느린 코드를 빠르게 만든다
X 빠르게 동작하지만 문제가 있는 코드를 올바르게 만든다.
글로벌 락을 써도 좋으니까 일단 올바르게 동작하는 코드를 만들어라. 가능하면 이를 검증하는 테스트를 만들어라.
성능이 아무리 중요해도, 제발 바보같은 애를 먼저 만들라고!
근데 성능이 정말 중요한 부분에서 부분에서 스핀락이 느려서 어쩌고 등의 걱정을 한다면 설계부터 다시 고민해봐 임마.
premature optimization is the root of all evil

7. core dump 는 신의 축복

8. 저장소에 대고 수다를 떨어
작업을 하다가 a. 빌드에 성공, b. 테스트 통과, 둘중 한가지라도 되면 작업 브랜치에 바로 커밋해라.
여러 변경이 한번에 묶여서 커밋된 것 보다는 쓸데없이 많은 커밋이 차라리 낫다.

9. 이름 잘 짓자
예를 들어 timestamp 를 ts 로 줄여서 변수명에 붙이고 있는데,
if (ts < client_ts) … 이런게 들어가면 나중에 고생한다. 비교문에 들어가는 변수명들은 가능하면 대등하게 한다.
server_ts vs client_ts 라던가 current_ts vs client_ts 라던가 …

변수 이름을 보고 그 정확한 의미를 자명하게 알 수 없다면 이름을 바꿔라.

생각의 체계에서 "자명한 블럭"이 어느 높이에 있는지는 매우매우 중요하다.

+ 조건을 if 에 바로 넣지 말고 true/false 리턴하는 "좋은 이름의 함수"로 분리하고, 테스트를 열심히 하자.


10. c++ 테스팅 프레임웍은 짜증난다

boost-python 이 컴파일은 느리지만(... 애도) 붙이긴 쉽다. 그냥 boost-python 으로 파이썬 바인딩 하고 파이썬 unittest 로 테스트 만들어도 쓸만하다.


11. 로그 및 콘솔출력

백그라운드 프로세스는 상태 확인이 쉽지 않다. syslog 같은 곳에 적절히 떨궈도 좋다. 다른 로그랑 섞이면 헷갈리니까 local0 같은걸로 파일 분리해서 남겨도 좋다. 여튼 어떻게든 상태 확인할 길이 필요하다. tmux나 screen세션에 띄워두는 경우도 간혹 생기는데 개발 단계에서만 하자. tmux, screen이 segfault를 내면서 세션에 있던 프로세스 모두 다 들고 자폭하는 경우가 꽤 있다. nohup 으로 돌려 놓는 경우에 콘솔 출력이 많다면 nohup.out 이 하드디스크를 모두 다 채우고 문제가 생길 수 있다. ... 몇달을 돌려둬도 로그파일이 하드디스크를 다 채울 일이 없어야 한다. 오래된 애를 어딘가 아카이빙 서버로 보내고 지우거나 ...


'Tech' 카테고리의 다른 글

Amazon glacier ... 를 쓸 뻔 했던 이야기  (0) 2012.08.23
회사일 하면서 삽질하거나 느낀거 끄적  (2) 2012.08.10
D2, array.reverse property has a side-effect. orz  (45) 2011.07.12
Thrift in D  (6) 2011.05.15
fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
Trackbacks 0 : Comments 2

D2, array.reverse property has a side-effect. orz

Tech 2011.07.12 17:29
얼마 전 코딩도장에서 N-Queen 문제를 손대본 적이 있다. 유명하고 어려운 문제라서 많은 사람들이 도전했고, 그만큼 효율적인 코드도 많이 알려져 있다. ... 코딩도장에서는 나이브하게 Coffeescript로 만들어 보고, 집에 와서는 요즘 연습 중인 D로 다시 만들어 보았다.

속도를 위한 최적화는 별로 없고, 그냥 무난하면서 Out-of-memory를 띄우지 않을 정도의 코드만 만들고 끝내야지 ~ 했는데, 테스트가 계속 실패한다. 각 Row에서 퀸의 위치를 Bit flag로 나타내는 식으로 보드를 저장하고 있었고, 실패하는 코드는 "현재 Queen의 위치 리스트" + "이번 Row에 놓고 싶은 Queen의 위치" 를 받아서 유효한지를 돌려주는 함수 부분이다.

테스트는 그냥 가볍게 이번에 놓고 싶은 Queen의 위치 - Row, Col - 에서 위로 한칸씩 올라가며 3개씩 확인하는 방식으로 했다.

(Row-1, Col), (Row-1, Col-1), (Row-1, Col+1)
(Row-2, Col), (Row-2, Col-2), (Row-2, Col+2)
...
(Row-k, Col), (Row-k, Col-k), (Row-2, Col+k)

이렇게 지금까지 놓인 Queen의 위치 리스트를 역으로 올라가면서 테스트를 하고 싶어서 이런 코드를 만들었다.

bool validate(in uint[] cur, in uint c) {
   uint l=c, r=c;
   foreach(uint _c; cur.reverse) {
       if (_c&c | _c&(l<<=1) | _c&(r>>=1))
           return false;
   }
   return true;
}

cur.reverse 가 뒤집힌 녀석을 리턴하는건지, 스스로를 뒤집는건지 잘 모르겠지만 cur 에 변화가 있다면 저기 달아놓은 in qualifier 가 못한다고 말해주겠지 - 라고 생각했다. in 은 const 를 강제하니까. 그리고 이녀석은 컴파일이 된다. 헤헤 안심 ~하고 다음으로 넘어가보자 했는데 ... 계속 테스트가 실패하네?

알아보니 reverse는, 1. 스스로를 뒤집고, 2. 그 뒤집은걸 리턴, 도 하는 녀석이다. 배열의 property 를 참조하면 배열 자체가 뒤집혀 버리는 상황. -_-; 뭐 이래? 거기까지면 괜찮은데 왜 컴파일이 된거야?. 어이가 없어서 위의 in 을 immutable 로 고치고 테스트 했는데, 역시 컴파일이 되고 실행도 된다. 아놔... ;; 결국 side-effect가 있는 property는 immutable, const 를 그냥 씹어 드신다는 뜻.

짧게 정리하면, 

import std.stdio;

int main() {
    immutable uint[] a=[1,2,3]; writeln(a); a.reverse; writeln(a);
    return 0;
}

이 코드가 컴파일+실행된다는 사실을 발견. ... 실행하면 [1, 2, 3] [3, 2, 1] 을 차례로 찍는다. 뭐라굽쇼? property 에 대해서는 수정 불가 조건을 검사하지 않는 것 같은데, 그 property가 side-effect 만땅 ... 이라는 암울한 상황이다. IRC에 가서 물어봤더니 돌아오는 대답은,

  1. Looks like a bug
  2. Those properties like reverse, sort will be deprecated.

였다. 으으, 아직 D 두번째 스펙이 불안정하다고는 하지만 이건 좀 지나친 거 아닌가 싶기도 하고.

-----
D 2.053, 2.054 에서 확인.

'Tech' 카테고리의 다른 글

Amazon glacier ... 를 쓸 뻔 했던 이야기  (0) 2012.08.23
회사일 하면서 삽질하거나 느낀거 끄적  (2) 2012.08.10
D2, array.reverse property has a side-effect. orz  (45) 2011.07.12
Thrift in D  (6) 2011.05.15
fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
Trackbacks 0 : Comments 45

Thrift in D

Tech 2011.05.15 18:03
Thrift를 포기할 수 없다 - D에서도 접근할 수 있으면 좋겠다 - 라는 생각이 들어서 약간 검색.

1. 누군가 구현하길 기다린다
Very promising. David Nadlinger라는 똑똑한 친구가 Google Summer of Code 에서 삽을 뜨려고 준비중인 듯 하다. D 포럼에서도 이름이 자주 보이는 친구이며, 홈페이지에서 볼 수 있는 몇몇 코드 조각으로 볼 때 무난히 (잘) 만들어 낼 것 같다.

2. 못기다리겠다.
훌륭한 사람이 삽을 떠서 결과가 곧 나올 것 같은 경우에 이렇게 조바심을 내는 것은 부질없겠다. 하지만 그래도 급하다거나, 연습삼아 해보거나 할 수도 있으니 잠깐 생각만 해보자. 사용하기 위해 보는 thrift 라이브러리는 크게 runtime 과 compiler 로 나눌 수 있다.

compiler는 protocol definition파일을 읽어서 목적 언어로 쓰여진 "코드" 를 뱉어주는 일을 한다. 이렇게 생성된 코드가 해당 언어로 준비된 "런타임 환경" 에서 돌아간다.

D는 C 혹은 C++과는 어느 정도 인터페이싱이 가능하다. 그렇다면, 무임승차 혹은 거기까진 안되더라도 코드 재사용을 생각해볼 수 있다. thrift 의 여러 생성 옵션 중에서 c_glib, cpp 정도가 살펴볼 만 하다. 어느 쪽이건 간에 D쪽에서 만지기 위해서는 interface를 만들어야 한다. 최소한 *.h -> *.di 로의 컨버팅이 필요한 것.

c, c++ 양쪽은 별도의 런타임 환경이 준비되어 있으며 include 되는 헤더도 다르다. 어느 쪽에 손을 대더라도 해야 하는 일은 별로 달라지지 않는다.

a. Runtime environment
ㄱ. Make custom environment with D
그냥 C 혹은 C++쪽 코드를 보고 D로 구현해버린다. 직관적으로, 여기서 API를 잘 설계하면 Compiler 쪽 작업이 대단히 쉬워질 것 같다.

ㄴ. Make interface to c_glib or cpp runtime
c_glib 혹은 cpp 를 위해 준비된 환경으로 인터페이스를 만들어서 가져다 쓴다. 이 경우 손으로 *.h -> *.di 컨버팅을 해주는게 좀 귀찮은 작업이 될 수 있다. ... 하지만 그냥 새로 만드는거에 비하면( .. )

b. Compiler
t_c_glib_generator, t_cpp_generator 이런 애들이 있다. runtime 쪽에서 직접 구현한다를 선택한 경우에는 그냥 t_d_generator 를 만들면 된다. 다른 생성기를 참조하고, 런타임 API가 잘 설계되어 있으면 그렇게 어렵진 않을듯 하다. 만약 runtime을 가져다 쓴다는 결정을 했다면, t_d_generator를 직접 만들 수도 있지만 다른 선택도 가능하다. 기존 Compiler 에 끼어들어서 *.di/*.d 파일을 *.h/*.cpp 파일과 함께 만들어 버리는 것. 지저분하지만, 런타임을 공유한다면 API도 같기 때문에 이렇게 작업할 수도 있다. 하지만, 이건 thrift 버전업이 있거나, 혹은 contribute를 하고 싶다면 심각한 문제가 된다. 다른 사람과 공유하지 못하는 삽이라니 가슴 아프지 않은가. dirty and quick.

David Nadlinger의 제안에서는 Free-riding없이 직접 구현을 택했다. CTFE(Compile Time Function Execution)도 고려중인 듯. 이 경우 일반적인 타입의 serialize/deserialize는 별 문제가 아닌데, rpc server/client implementation 에서 비동기를 구현할 때 곤란할 수 있다(포기하고 그냥 스레드 만세 할 수도 있지만). 현재 latest인 D2.053 epoll|kqueue|iocp 등이 core.sys.posix|osx|windows 에 없다. D1을 고려한다면 tango를 볼 수도 있지만, 미래를 생각한다면 볼때 D1+Tango로 새 프로젝트를 시작하는건 삽질 ( ... )이라는게 중론이다. libevent의 D port도 아직은 없어뵈고... 그렇게 어렵진 않겠지만, 역시 이런 인터페이스를 뚫는 작업이 좀 지루할 수 있겠다.

결론적으로 무임승차는 못할 듯. 어느 쪽으로 가더라도 손이 가는 작업이 필요하다.

core.sys.posix.poll 도 있는데 core.sys.posix.epoll 정도 있어주면 어디가 덧나나. 이미 삽이 준비되지 않았으면 github 에 자리 하나 차리고 해보려 했으나 일단 기다리기로 결정함. 크릉크릉. thrift 와는 별도로 libevent 헤더들을 D interface 파일로 만들어 두는건 해볼만 할듯. 어렵지도 않고, 시간만 들이면 되는거고, 써먹을 데도 많다. 이미 있는데 못찾는건가 ... ... ...

tags : d, d2.053, libevent, thrift
Trackbacks 0 : Comments 6

fix: ugly gitweb page

Tech 2010.12.12 16:38
debian testing 을 쓰고 있는데, 어느날 갑자기 css, js, images 기타등등을 못읽어와서 페이지가 안이뻐( .. ) 졌다. 뭐컨텐츠 자체는 문제가 없어서 그냥 뒀는데 - 안이쁘니까 괜히 찜찜한 상태 .. ..... ......... 간만에 귀차니즘을 이기고 약 10분을 투자해서 수정.

gitweb.css, gitweb.js, git-logo.png 등등을 읽지 못하게 되어서 생긴 문제이다. 이게 버전 업글이 되면서 기본 디렉토리나 설정이 바뀐건지는 잘 모른다 ... =_= 대체 언제부터 삑살났던거지... 혹시 나처럼 귀차니즘에 시달리는 사람이 있다면 참고를.

1. 못가져오는 파일들은 /usr/share/gitweb 여기에 있다.
2. ln -s /usr/share/gitweb /var/www/gitweb
3. Add Alias /r/ "/var/www/gitweb" to /etc/apache2/site-enabled/gitweb - 이건 사람 나름이지
4. Modify /etc/gitweb.conf like this:
"gitweb.css" -> "/r/gitweb.css"
"gitweb.js" -> "/r/gitweb.js"
... ... ... and so on.
5. restart apache

한동안 많이 놀았으니 다시 소일거리나 시작해 볼까나.

'Tech' 카테고리의 다른 글

D2, array.reverse property has a side-effect. orz  (45) 2011.07.12
Thrift in D  (6) 2011.05.15
fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
자바스크립트로 벽돌깨기를 만들어보고 싶은데 ... ...  (5) 2010.07.24
Bit count with CUDA (T_T)  (3) 2010.05.16
tags : gitweb, ugly page
Trackbacks 1 : Comments 3

(1/2) Programming in clojure

Tech 2010.08.08 13:35
Programming in Clojure 를 지르고 3일. 이건 뭐하는 녀석일까? 라는 세근세근한 기분으로 책을 한번 주욱 훑어보고, 몇 개의 짧은 코드를 만들어 보았다. 더불어 이맥스에도 붙여 보고 ... 그리고 천천히 다시 읽기 시작해서 절반 정도. 여기까지 보고 난 감상(?)을 정리한다. 나머지 절반을 더 읽고 나서는 지금의 생각이 번복될 수도 있다.

  * 설탕문법으로 가득하다

    이건 좋다/나쁘다로 나누기는 좀 어려운 부분이다. 전체적으로는 리습 방언에 항상 따라다리는 Bad-point 인(역시 사람차가 나지만) **괄호난무**에 대한 방비가 좀 있다. 예를 들어서,

(let ((a 1)
      (b 2))
  (+ a b))

이런 스킴(리습?)코드가 클로져에서는

(let [a 1
      b 2]
  (+ a b))

이렇게 풀린다... 잘 보면 괄호를 하나 덜 사용했다. 이것 말고도 괄호의 Depth를 줄이고자 한 노력이 엿보인다. ... 하지만 이로써 <코드 자체가 Parsing tree> 라고 하기에는 조금 어려운 듯도 하고, 아닌 듯도 하고 ... 책에서는 가끔 저 Bindings 부분을 이렇게 풀어놓곤 하는데, 처음 봤을때 헷갈려서 약 3분 정도 정신을 못차렸다.

(let [a 1 b 2] (+ a b))

이렇게 써놓으면 a<-1, b<-2 처럼 안보이잖아... ㅠ_ㅠ 당황했다규... ㅠ_ㅠ

그 외에도 "한 가지 일을 하기 위한 여러가지 설탕" 들이 존재한다. 내가 처음... 은 아니고 가장 오랫동안 만지고 있는 리습 방언인 스킴은, SICP를 통해서 접해서인지는 몰라도 "문법을 기억 할 필요가 없는 언어" 였는데, 클로져는 그렇지는 않다. 물론 교육용으로 디자인된 언어랑 비교하는거니 공정하진 않지만, 이렇게 기억할게 많은거(그래봐야 자바나 C++에 비하면...) 어려운데... 그래도 손에 조금만 익숙해지고 나면, 큰 어려움 없이 다른 리습 계열 언어에서 만들던 코드를 클로져로도 만들 수 있다.

주의할 사항은 - 책에서도 주의하라고 나온다!

(if '()
    true
    false)

빈 리스트가 nil 이 아니다, 빈 리스트는 참이다, 라는걸 주의해서 기억해야 한다.

그 외에, 스킴과 들여쓰기 컨벤션이 좀 다른 듯 한데 이거 은근히 신경쓰인다. ㅠ_ㅠ

  * 자바와 이다지도 가깝다니...!

    난 자바에 그다지 익숙하진 않지만, 클로저로 코드를 만들다가 - 어... 이거 빌트인이 있을 것 같은데 모르겠어...?? - 정도의 느낌이 들면 그냥 javadoc 을 띄워 찾은 다음에 자바쪽 API 를 사용해버릴 수 있을 정도로 쉽다. JVM위에 올라간다는 건 이런 것인가... 우왕 +_+

내가 자바에 조금 더 익숙했더라면, 이것 저것 많이 해볼 수 있었을텐데 - 자바랑 친하게 만들어놔도 내가 자바랑 안친해서 ... 그래도 방대한(맞지?) 자바쪽 라이브러리들을 쉽게 가져다 쓸 수 있다는 점은 매력적일듯. 거꾸로도 마찬가지이다. 클로져로 만든 함수들을 자바에서 가져다 쓰는 것도 쉬운 듯 하다.

-- Clojure's functions implement Runnable and Callable.

  * Functional?

    책에서는 몇 장에 걸쳐 장황하게 Sequence를 다루는 여러가지 빌트인들에 대한 이야기를 한다. 그 자체는 Lisp 방언이라는 관점에서 별로 특별한 것은 없고, 그 여러가지 Seq-able 아이들이 Java collection 과 어떻게 연결되는지에 대해 간간히 나오는 설명이 꽤 중요할 것 같다. ... 자바쪽의 피쳐를 잘 가져다 써야 클로져가 의미있는거잖아? - 자바와의 Integration 없이 언어 스펙만 보면 딱히 특별한 점은 그다지 ... - STM이 언어 스펙이라고 하면 좀 도드라져 보일 수도 있겠지만! ... 혹 이런 류의 개념들에 익숙하지 않다면 - Pure java/C/C++ programmers - 책에서 설명하는 sequence(Lazy evaluated!)에 대해 잘 읽어보고 감을 잡는 것도 좋을 듯 하다. 혹시나 파이썬 유저라면, itertools 패키지를 잘 뒤져보면 ... ...

  * Rich Builtins/Libraries

    (아마) SICP만 봐서 그런거겠지만, 언어에 딸려오는 기본적인 피쳐들이 (Scheme 에 비해서) 풍부하다는 사실에 감동. SICP에서 하나씩 직접 구현했던... 많은 것들을 그냥 쓸 수 있다. 사실 이건 클로져가 아니라 clisp 에서도 마찬가지일텐데(ㅠ_ㅠ), 그래도 좋은건 좋잖아.

게다가 - 위에서 한 이야기와 중복이겠지만 - 자바쪽 API가 거의 언어 빌트인 수준으로 노출되어 있어서 아예 레퍼런스로 javadoc을 띄워놓고 작업해도 될 정도라서, 우왕ㅋ 굿ㅋ.

남은 절반은 다음 주 중에 읽고 리뷰 2/2 를 후다닥 쓰자.

-----

클로져와 직접적인 연관이 있는 것은 아니지만, 책에서 기억나는 구절을 하나만 뽑아본다면:

-- Don't write ugly code in search of speed. Start by choosing appropriate algorithms and getting your code to simply work correctly. If you have performance issues, profile to identify the problems. Then, introduce only as much complexity as you need to solve those problems. - 격하게 공감 =3=3

리팩토링, TDD 같은 류의 책에도 조끔씩 핀트는 다르지만 큰 맥락에서는 비슷한 얘기들이 많이 등장한다. Complexity는 보이지 않는 곳에 추상화시켜 던져 둘 수 있는 것이 좋고, 그렇다면 Simple and Naive code 를 나중에 바꿔치기 하는 접근이 어느정도 <추상화를 강제/유도> 할 수 있다.

'Tech' 카테고리의 다른 글

Thrift in D  (6) 2011.05.15
fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
자바스크립트로 벽돌깨기를 만들어보고 싶은데 ... ...  (5) 2010.07.24
Bit count with CUDA (T_T)  (3) 2010.05.16
iterator invalidation  (5) 2010.05.10
Trackbacks 0 : Comments 4

자바스크립트로 벽돌깨기를 만들어보고 싶은데 ... ...

Tech 2010.07.24 02:02

일단 아무렇게나 그림 그리기 시도. 이정도면 데탑에서는 할 수 있을 것 같다. 느리진 않네...

하지만 아이폰 ... ... OTL?

'Tech' 카테고리의 다른 글

fix: ugly gitweb page  (3) 2010.12.12
(1/2) Programming in clojure  (4) 2010.08.08
자바스크립트로 벽돌깨기를 만들어보고 싶은데 ... ...  (5) 2010.07.24
Bit count with CUDA (T_T)  (3) 2010.05.16
iterator invalidation  (5) 2010.05.10
사용소감2: Google protocol buffer  (1) 2010.02.11
Trackbacks 0 : Comments 5

Bit count with CUDA (T_T)

Tech 2010.05.16 23:42

왠지 빨리 계산해보고 싶은게 있어서 이틀쯤 고민해보다가, 알고리즘으로는 내 머리에서 더 나오지 않아서 하드웨어적인 도움을 받아보는건 어떨까 생각했다. 틀은 CUDA API로 쉽게 만들 수 있을 것 같아서 메인함수에 꾸역꾸역 밀어넣기로 뚝딱.

그런데, 아무리 개떡같은 코드에 카드도 9500GT(OTL)라지만 GPU Accelerated가 CPU(코어 하나만 사용)보다 느리면 어뜩해. ㅠㅠ

코드 불량이라고 생각하고 싶지만, SDK 에 포함된 벡터계산 샘플 코드의 1. GPU에 던져서 계산, 2. CPU로 재계산해서 검증, 부분의 시간을 재어봤더니 여기도 GPU부분이 CPU보다 느렸다. 코드만의 문제는 아니라는 것.

음... 뭐 작업을 쪼개서 양쪽을 다 쓰면 결과적으로 빨라지긴 할 것 같은데 x100 faster 이런건 좀 무리일려나 싶다. 코드가 바보라도 말이지, GPU/CPU 양쪽다 똑같은 바보코드니까 대강 계산 속도에 비례해서 나와줘야 할 것 같은데 ...

... 9500GT 가 ㅂㅅ이라서 그런걸까? 라는 생각으로 다음주에 회사에 있는 Tesla를 꿀꺽-_-/ 해서 놀아봐야겠다.

Elapsed time with GPU: 0.87000s
Elapsed time with CPU: 0.66000s

대략 2억개 가량의 바이트에서 0번~7번 비트에 등장하는 1이 몇개인지 세는 작업이다. CPU 로 계산할 때에는 적당한 단위로 테이블 룩업하면 더 빨라질 수도 있을 것 같긴 한데 ... CUDA님은 어떨지 테스트를 한번 해볼까.

혹시 이 외에 N배 더 빠르게 할 수 있는 방안이 있으신 분은 저에게 하겐다즈 아이스크림을 요청하세요.
.
--
P.S CPU에서 테이블 참조를 했더니 2배쯤 빨라졌다. CUDA 커널에서 테이블 참조를 했더니(어디서 합치는지에 따라 몇가지 variation을 만들어서 해봤지만) 5배쯤 느려졌다. ... ㅠㅠ CPU: 0.28XXXX 정도... CUDA레퍼런스에

<캐시 참조보다 재계산이 빠를 수 있다>

고 자랑스럽게(-_-) 쓰여있던데, 느낌이 새롭다. 음...

<캐시 참조가 재계산보다 느릴 수 있다>

랑 똑같은 말이긴 한데.
tags : 9500GT, CPU, cuda, CUDA C, GPU, Tesla
Trackbacks 0 : Comments 3

iterator invalidation

Tech 2010.05.10 17:08
의외로 이런 실수를 하는 사람이 꽤 많다.

numbers = range(100)
for x in numbers:
    numbers.remove(x)

이렇게 하고 나면 numbers 는 어떤 모양이 될까? 아마도 코드 작성자의 의도는 하나씩 모두 날려서 [] (빈 리스트)가 나오는거였을텐데, (내 맘대로 추측)

>>> print numbers
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
>>> 

실제로 해보면 이런 녀석이 남는다. 왜 그럴까? 참고로 - for x in numbers[:]:, 혹은 for x in list(numbers): 이렇게 for statement 를 고치면 의도대로 동작하긴 한다. 그렇다고 좋은 코드라는건 아니고 ...

무슨 언어에선가는 반복중인 컨테이너를 고치려고 하면 컴파일 타임에 알려준다고 하는 것 같았는데 ... 이런 류의 버그는 은근히 찾기가 어렵다. 간단한 (정말 기초적인) 테스트 코드 정도로도 조기 발견이 가능한 부분이고, 가능하면 테스트에서 잡히기 전에 코더의 본능이 먼저 경고해 주어야지.

그래도 STL 에는 "이 녀석은 반복자를 무효화시킵니다 ~ 조심하세요 ~" 라고 레퍼런스가 말해주긴 하는데, 파이썬 레퍼런스엔 그런 이야기가 없었던 것 같다. - 날로 읽어서 확실치는 않다.

... 사실 이건 SICP 3장이 떠올라서 주절거리는 글이다. 저 비슷한 느낌으로 스트림을 생성해가는 ㅂㅌ적인 코드들... OTL. compound but tricky 라는 느낌이랄까. 내가 수학을 못해서 그렇게 느끼는걸지도 모르지만.

아 피곤해. 두서없는 글이 되었구먼. 결론은 내가 부족하다는 거? (저건 내가 만든 버그는 아니다)

Trackbacks 0 : Comments 5

사용소감2: Google protocol buffer

Tech 2010.02.11 14:20
빠르다길래 믿고 그냥 가져다가 쓰고 있었는데, 테스트 코드를 돌릴 때는 모르다가 진짜 데이터( ... ) 들이 들어가기 시작하니 시스템 퍼포먼스가 말도 안되도록 떨어졌다. 여기서 한번 피 토해주고 (쿨럭) ... 아, 빠르다는건 <XML에 비해서>인 듯 하다. 이거 머야 대체! 하면서 프로파일링을 해봤는데, ... 응?

SerializeToString, ParseFromString

이녀석들이 나란히 1등, 2등?

패인은 repeated 에 있었다. 몇 가지 부가 정보와 함께 수십만(최대 백만 정도)개의 32bit integer 들을 빠르게 주고받는 시스템인데, 이걸 repeated uint32 id_list; 같은 식으로 만들어 사용했다. 이 녀석을 Serialize, Parse 하는 부분이 대박이었던 것. 테스트 할 때에는 적당히 수백개 정도만 넣어봐서 차이를 잘 못느꼈는데, 이게 커지니까 ... ... -_-a

아마 타입검사라던가, ... 때문이 아닐까 한다.

dgoon@katy:~/works/pb2$ cat test.proto 
message Test {
    repeated uint32 id_list = 1;
};
dgoon@katy:~/works/pb2$ protoc --python_out=. test.proto 
dgoon@katy:~/works/pb2$ cat test.py
import cPickle
import random
from array import array
from test_pb2 import Test

def elapsed(stmt):
    import time
    st = time.time()
    exec(stmt)
    return time.time() - st

test_arr = [r for r in xrange(100000)]

msg_pb2 = Test()
msg_pb2.id_list.extend(test_arr)
arr = array('I', test_arr)
print('pb2 ser: %5.4f' % elapsed('msg_pb2.SerializeToString()'))
print('pb2 ser-par: %5.4f' % elapsed('Test().ParseFromString(msg_pb2.SerializeToString())'))
print('pickle ser: %5.4f' % elapsed('cPickle.dumps(test_arr)'))
print('pickle ser-par: %5.4f' % elapsed('cPickle.loads(cPickle.dumps(test_arr))'))
print('array ser: %5.4f' % elapsed('arr.tostring()'))
print('array ser-par: %5.4f' % elapsed('array("I").fromstring(arr.tostring())'))
dgoon@katy:~/works/pb2$ python test.py
pb2 ser: 0.3849
pb2 ser-par: 0.9537
pickle ser: 0.0400
pickle ser-par: 0.0823
array ser: 0.0004
array ser-par: 0.0006
dgoon@katy:~/works/pb2$ 

그래서 결국에는, array.tostring() 을 사용해서 뽑은 문자열을 프로토콜 버퍼에 bytes 타입으로 붙여서 보낸 다음 (with packed_ prefix) 사용하는 시점에 array.fromstring()푸는 형태로 고쳤다. 일단 이렇게 속도는 잡았는데 ... ... 크흑, 귀찮아. 프로토콜 버퍼가 생성한 객체를 확장해서 써야 할 것 같다.

'Tech' 카테고리의 다른 글

Bit count with CUDA (T_T)  (3) 2010.05.16
iterator invalidation  (5) 2010.05.10
사용소감2: Google protocol buffer  (1) 2010.02.11
사용소감: Google protocol buffer  (4) 2010.02.04
TDD: 켄트백아저씨가 쓴 책이지?  (2) 2009.12.29
git/git-svn on working machine  (2) 2009.12.17
Trackbacks 0 : Comments 1

사용소감: Google protocol buffer

Tech 2010.02.04 16:57
일단 관련 링크 몇개


회사에서 새로 만드는 시스템을 크게 몇 개의 컴포넌트로 잘라서 디커플링을 시도했다. 시스템 전체를 흐르는 데이터가 거치는 각 단계마다 투입되는 자원량을 조절할 수 있어야 하며, 머신도 나뉘어야 ... 하고 코드 의존성도 님하 좀 ㅠㅠ

이 과정에서 함수 인자, 혹은 글로벌 자료구조 등으로 공유하던 데이터를 넘겨줄 방법 - 그러니까 IPC - 이 필요하게 되었고, 대부분의 정보 전달을 Queue with Persistent layer 로 대체할 수 있었다. 반응성보다는 단위 시간당 처리량이 중요한 시스템이라서 ...

여러개의 큐 서버가 만들어지고, 여기에 데이터를 넣고 빼고 하게 되는데 이 과정에서 딸려오는 귀차니즘이 소켓통신. 그리고 몇 가지 이유로 인하여 큐 서버를 포함하여 관련되는 코드들이 자바/C/C++/Python 들이 섞일 수 있는 가능성을 가지게 되었다. (사실 이게 디커플링의 의도중 하나이긴 한데 ...)

파이썬만 있다면야 pickling 이라는 편한 방법이 있지만, 다른 언어가 들어오면 조금 골치아파지고... 이런 상황에서 Google protocol buffer 가 떠올라서 가져다 사용. 가장 큰 특징은,

  1. Code generation
  - 유피넬의 누군가(...)가 세미나에서도 이야기했던 방법인데, Definition data structure -> Code to handle 방향으로 코드를 생성해 버린다. 코드 레벨에서 서버/클라를 포함한 이 데이터를 다루는 녀석들이 모두 공유할 수 있다.
  - 코드 생성이기 때문에, 오타라던가 ( ... ) 양쪽 코드의 불일치 등으로 생기는 문제는 거의 제로
  - 데이터 정의가 바뀌면 코드 생성->컴파일->링크 를 다시 해야 한다
  - 이 툴(그러니까 google protocol buffer)를 도입함으로써 생기는 제약이 별로 없다 - 프레임웍을 가져다 쓰는거에 비하면야...

  2. Structured data definition
  - 일반적인 클래스 디자인과 비슷하게 데이터를 정의할 수 있다
  - 만들어진 데이터 타입들을 조합하여 복잡한 블럭을 만들 수 있다

  3. Language support
  - 고려중인 Java/C++/Python 세가지 모두 코드를 찍어내준다
  - 언어와 상관 없이 이 코드들은 서로 호환되는 데이터를 만든다 (Serialize/Parse 결과가 일치한다는 뜻)

그리고 부가적으로 빠르다, 같은게 있긴 하다. ... 하지만 아직 확인해보진 않았으니 뭐 ... 그래봐야 내가 직접 만든 코드보다 백만배 빠르진 않겠지... 훌륭한 점은 퍼포먼스 저하를 최소한으로 막고(과연 그럴까?는 코드를 까봐야 알겠지만...) 사용하기 편해졌어! 를 확보한 것, 이라고 생각할 수 있는데.

뭐 이 장점들은 확실히 강력한 것 같다. 단점은... Composite type 에 대한 assignment를 막아놓은게 좀 귀찮은데, 이건 내부 구현에 따라오는 이슈인 것 같다. 로직에서 다루는 데이터 타입과 데이터 주고받기에 쓰이는 타입이 다르면 - 로직에서 프로토콜 버퍼 객체를 사용하지 않으면 - Send/Recv 할 때 데이터의 복사가 한번 일어나게 되는데 이건 좀 곤란한 것 같다. ... 하지만, 잘 살펴보면 보내거나 받는 데이터를 Stream으로 만들어서 해결할 수 있을 것 같기도 한데, 지금은 튜토리얼만 슥 보고 대충 가져다 쓰는거라 뭐 ... 복사 없이도 처리가 가능할 것 같긴 하니까 이건 패스.

큰 코드조각은 아니지만, 유용한 걸 잘 만든다. 구현 자체는 논외로 하고, 컨셉이 좋지. (더불어 리카님도 굿 ㅋ) 어느 정도에서 Abstraction layer를 만들어야 사용성을 최소한으로 해치면서 Drawback을 줄일 수 있을지 - 에 대한 감이 좋아 보인다. 이런건 좀 배우자.

쓰고 나서 보니 소감이라기엔 좀 이상하다. 그냥 "써봤음" 문서. 낄낄낄.

'Tech' 카테고리의 다른 글

iterator invalidation  (5) 2010.05.10
사용소감2: Google protocol buffer  (1) 2010.02.11
사용소감: Google protocol buffer  (4) 2010.02.04
TDD: 켄트백아저씨가 쓴 책이지?  (2) 2009.12.29
git/git-svn on working machine  (2) 2009.12.17
Links on xml and related techs  (1) 2009.12.09
Trackbacks 0 : Comments 4

TDD: 켄트백아저씨가 쓴 책이지?

Tech 2009.12.29 09:59
그냥 뒤적여만 보고 처음부터 끝까지 주욱 읽은적은 없었다.

손에 잡혀서, 이번에는 - 이라는 생각으로 한번에 끝까지 읽었다. 대부분이 '보여주기' 이기 때문에, 쉽게 따라갈 수 있어서 시간은 얼마 안들었다.

결과 ... 를 말하기 전에 일단 확실히 할 것:
  1. TDD와 Unittest는 다른거다
  2. 테스트 먼저 쓴다고 TDD는 아니다

그리고 결과:
  클린 코드는 테스트 주도적으로 만들어질 수'도' 있다.
  Clean code that works - 가 만들고 싶다는 켄트백 씨는, 한줄짜리 테스트로부터 짧은 싸이클로 코드가 변해가는 과정을 보여주었다. 아, 그래, Impressive. 하지만 그 뿐. 예를 위해 극단적으로 짧은 주기를 가져가긴 했지만, 그렇지 않은 경우라고 해도 분명 Pencil and Paper 로 시작하는 것이 Clean code that works 로 가는 지름길이라고 생각한다. (아, 그래 그냥 내 생각이 그렇다는 거다)

유닛 테스트 자체의 효용성과, 테스트 코드가 코딩 처음 단계가 된다는 아이디어, 테스트 추가-컴파일-테스트 통과-리팩토링 의 사이클 ... 대부분의 내용은 좋은 내용(이고 공감도 하는 내용)이긴 한데. Test-driven 에 대해서는 글쎼(?????). 예가 좀 구질구질해서 그런가 책이 보여주는 예제(특히 첫번째 currency) 자체가 TDD에 집착하다 말아먹기 - 그러니까 It passes the test, so it might work. But I can't tell why - 딱 좋아 보인다.

물론 켄트백 아저씨가 그런 건 아니겠지만, 의도했건 안했건 TDD는 꽤나 Dogmatic(적절한 한글/한자어 표현을 못찾겠다. 독단적인... 이랑은 쫌 뉘앙스가 다른데 ...)한 분위기로 쓰여 있어서 읽고 쉽게 집착하게 되는 책이다. Limitation이 이런게 있어 라고 말해주고는 있지만, 신경 안쓰고 집착하기 쉽다는 이야기. 그리고 그 집착이 묘-하게 꼬이기 시작하면 문제가 시작된다. 도구는 도구일 뿐, 집착하지 말자. - 내 얘기는 아니고 ...

경우에 따라선 잘 맞을 때도 있겠지 뭐 ... (경우에 따라선 안 맞는 때도 있겠지 - 라고 하지 않았다는데 주목)

Unittest의 적극적 도입 - 이 개발 프로세스를 획기적으로(정말 획기적으로!) 바꾸었다고는 생각하지만, TDD라는 방법론 자체는 도구의 하나로 제시된 것이고 - 패러다임 Shift 을 야기할 정도로 강력한 것은 아니었다, 라는 내맘대로 총평. 위에서 말했듯이 (Unittest의 적극적 도입 != TDD)

... ... ...

여담으로, 이미 위에서 들키긴 했지만 디군은 PP(Pencil and Paper) Driven Developement 에 집착하는 것 같은데, 역시나 이것도 꽤 곤란한 경우가 있는 것 같다. 근데 다른 집착과 마찬가지로 (알면서도) 쉽게 안고쳐진다. 쿨럭쿨럭 ---


'Tech' 카테고리의 다른 글

사용소감2: Google protocol buffer  (1) 2010.02.11
사용소감: Google protocol buffer  (4) 2010.02.04
TDD: 켄트백아저씨가 쓴 책이지?  (2) 2009.12.29
git/git-svn on working machine  (2) 2009.12.17
Links on xml and related techs  (1) 2009.12.09
SICP 근황  (8) 2009.12.01
Trackbacks 0 : Comments 2

git/git-svn on working machine

Tech 2009.12.17 14:01
회사에서는 소스코드 저장소로 svn 을 사용하고 있다. 음... 음... 그런데, 내 로컬머신(...)과 개발서버의 내 홈디렉토리 양쪽에서 변경이 일어나는데 이걸 서로 싱크시키거나 할 때 꽤나 귀찮아진다. 심지어 귀차니즘이 절정에 달할 때에는 그냥 central repository에 커밋->저쪽에서 update 이런 식으로 소스코드를 공유(당연히 테스트 되지 않은 코드)하기도 하고 ...

그런데 어느덧 head revision이 2만3천을 넘어가기 시작하고, 이런 저장소 오염을 다른 사람들에게 보이기 부끄럽기도 하고 ... 하여 생각한 것이 git. 아, 분산 저장소를 만져볼 때가 됐구나, 라는 느낌표가 왔다. 지금까지는 튜토리얼 정도만 보고 필요성을 크게 느끼지 못해서 그냥 그런게 있지, 라고만 넘어왔는데, 이제 때가 됐다.

-----

약간의 삽질: git-svn 패키지를 설치했는데 git-svn 커맨드가 없다? git svn 이런 식으로 git 안의 서브커맨드로 쓰면 된다. ... 한참 헤맸다. ㅠㅠ

-----

이렇게 가져와서: git svn clone repository_path
이렇게 저장소와 동기화 시키고: git svn rebase
이렇게 커밋하면 된다고: git svn dcommit

이건 중앙 저장소와 이야기 할 때만 하면 되고, 그냥 내 작업은 바로바로 로컬에서 git 으로 할 수 있다.

진작 이럴껄...

-----

그런데 그냥 clone 가져오면 리비전 2만3천개를 차례대로 가져오게 되서 좀 시간이 걸린다. 헤드만 가져올 수도 있긴 한데 ... 뭐, 그냥 ... 


'Tech' 카테고리의 다른 글

사용소감: Google protocol buffer  (4) 2010.02.04
TDD: 켄트백아저씨가 쓴 책이지?  (2) 2009.12.29
git/git-svn on working machine  (2) 2009.12.17
Links on xml and related techs  (1) 2009.12.09
SICP 근황  (8) 2009.12.01
django 삽질  (3) 2009.11.19
Trackbacks 0 : Comments 2

Links on xml and related techs

Tech 2009.12.09 18:19
gateway:

'Tech' 카테고리의 다른 글

TDD: 켄트백아저씨가 쓴 책이지?  (2) 2009.12.29
git/git-svn on working machine  (2) 2009.12.17
Links on xml and related techs  (1) 2009.12.09
SICP 근황  (8) 2009.12.01
django 삽질  (3) 2009.11.19
CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Trackbacks 0 : Comments 1

SICP 근황

Tech 2009.12.01 20:47
3장 연습문제를 풀다가, 스트림이라는 아이가 나왔다.

cons-stream, delay 등등을 "이렇게 동작해" 라면서 코드를 보여주는데, 얘네들이 보여주는 코드를 가지고 문제를 풀면 스트림이 스트림이 아니게 된다.

(stream-enuerate-interval 0 100000)

이런걸 만들면, 만드는 순간 모두 evaluation 되어 버리는 것. 그 이유는,


여기 각주에 있음. 요는 cons-stream, delay 가 Special form 이 아니라 Function 이면 방법당한다는 것. 천천히 코드를 따라가 보면 당연하다. 책에서 주는 정의대로 하면 스트림이 부지런해져서 만들어지는 순간 끝까지 다 생긴다규 ㅠㅠ

mit-scheme 에는 빌트인으로 cons-stream 이 있어서 이걸 써서 하면 제대로 동작한다. PLT-scheme 에서도 뭔가 할 수 있긴 한것 같은데, 그건 컴키드님이 찾아서 메일링 리스트에 공유해주실 듯.

아 짱나 =3=3

Add:
PLT-Scheme 에서,
  1. 언어를 "Module" 로
  2. 소스코드 맨 위에 "#lang planet neil/sicp" 를 한줄 넣는다
실행하면 뭔가 받아와서 설치함. ... SICP 연습문제들 돌릴 수 있음. ... 책에 정의된 cons-stream, delay 를 쓰고 있다면 지우자. 뒤쪽 infinite-stream 에서 방법(무한시간+공간)당한다.

'Tech' 카테고리의 다른 글

git/git-svn on working machine  (2) 2009.12.17
Links on xml and related techs  (1) 2009.12.09
SICP 근황  (8) 2009.12.01
django 삽질  (3) 2009.11.19
CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Parameter vs Argument  (3) 2009.01.21
Trackbacks 0 : Comments 8

django 삽질

Tech 2009.11.19 15:59
아무래도 한글 데이터를 처리하지 못해서 끙끙대다가 원인을 찾았다. DB(mysql)를 만들때 charset 지정이 엄한걸로(latin...) 되어 있었던 것.

create schema dgoon default charset utf8;

썩을.

'Tech' 카테고리의 다른 글

Links on xml and related techs  (1) 2009.12.09
SICP 근황  (8) 2009.12.01
django 삽질  (3) 2009.11.19
CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Parameter vs Argument  (3) 2009.01.21
GEB: MU puzzle  (4) 2008.10.20
tags : Django, MySQL, utf8, 한글
Trackbacks 0 : Comments 3

CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)

Tech 2009.09.17 11:16
ATI를 선호하는 디군이 왜 이번에 Geforce9500GT라는 허접한 물건을 샀는가? - 디군의 개인적인 판단임

CUDA API 를 만져보고 싶었기 때문이다.

그래서 어제 집에서 사용하는 우분투 머신에 CUDA 개발툴이라는 녀석을 깔았는데, 아주 약간( ... ) 삽질을 했다. 나중에 다시 이 짓을 할 수도 있으므로 정리해두자.

-----
1. 준비물

  * CUDA 지원하는 NVIDIA 그래픽 카드 Geforce 8***, 9*** 이상은 모두 된다. 여기(http://kr.nvidia.com/object/cuda_learn_products_kr.html)에 자신의 그래픽카드가 있으면 된다. 나는 Geforce 9500GT 를 준비했다.


2. 설치할 때 귀찮은 점들

여기(http://kr.nvidia.com/object/cuda_get_kr.html) 서 시키는대로 Driver->Toolkit->SDK 순으로 설치하면 된다. 사실 순서가 중요한 것은 아니다. 디군의 경우는 삽질을 좀 해서 드라이버를 가장 나중에 했지만 별 문제는 없었다.

윈도우 환경이라면 (해보진 않았지만) 별 문제가 없을 것 같고, 리눅스 환경에서 약간 귀찮은게,

  * NVIDIA 드라이버를 설치할 때 X 가 떠 있으면 안된다
  * 반드시 사용중인 드라이버를 제거해야 한다

두가지이다. 나는 저 두번째 이유로, 삽질해서 드라이버를 마지막에 다시 설치했다.

 - 우분투의 경우 시스템->관리->하드웨어드라이버, 에 가서 현재 사용중인 드라이버를 쉽게 deactivate할 수 있다.
 - X 내리고 드라이버 설치: Ctrl+Alt+Fn 으로 세션을 옮겨다닐 수 있는데, 보통 1-6까지는 터미널이고 7번에 X가 떠 있다. 아직 예외는 본적이 없다. 이걸 이용해서 Ctrl+Alt+F1 로 1번 세션에 가서 로그인 한 다음

/etc/init.d/gdm stop
--- install driver as root
/etc/init.d/gdm start

해주면 된다. 그냥 깔끔하게 리붓해도 굿. 사용하던 드라이버를 제거해주지 않았다면, 여기서 커널이 "아썅 왜 버전 두개가 섞여있어!" 라면서 짜증을 내면서 디바이스를 못잡는다. 주의하자. 게다가 저 짜증을 바로 보여주는게 아니라 커널 로그를 까봐야 나온다. 겉으로 보기에는 "그냥 못잡네" 정도로 보이기 때문에 ... -_-

참고로, Driver, Toolkit, SDK 모두 executable이므로, 다운받고 나서 실행권한이 없다고 하면 chmod +x filename 혹은 sh filename 같은 식으로 실행해주면 된다. 이거 물어보는 녀석이 있더라고 ... -_-a


3. Toolkit, SDK 설치

 그냥 다운받은 파일을 실행하면 된다. 아 쉽다. SDK는 기본 경로가 사용자 로컬이다. 모든 사용자를 위해 설치하고 싶다면, root 권한으로 어딘가 적당한 곳에 설치해주면 되겠지만 굳이 그럴 필요가 있을까 ... (있을지도)


4. Build SDK

SDK를 설치한 경로가 ~/NVIDIA_GPU_Computing_SDK 라고 하자. (기본이다)

cd ~/NVIDIA_GPU_Computing_SDK/C
make

이렇게 빌드하면 되고, 빌드 후 생기는 예제코드의 실행파일들은 ~/NVIDIA_GPU_Computing_SDK/C/bin/linux/release 에 생긴다. CUDA가 제대로 동작한다면,

~/NVIDIA_GPU_Computing_SDK/C/bin/linux/release/deviceQuery

를 실행해서 device에 내 그래픽카드가 보이면 된다.

dgoon@katy:~/NVIDIA_GPU_Computing_SDK/C/bin/linux/release$ ./deviceQuery
CUDA Device Query (Runtime API) version (CUDART static linking)
There is 1 device supporting CUDA

Device 0: "GeForce 9500 GT"
  CUDA Driver Version:                           2.30
  CUDA Runtime Version:                          2.30
  CUDA Capability Major revision number:         1
  CUDA Capability Minor revision number:         1
  Total amount of global memory:                 536150016 bytes
  Number of multiprocessors:                     4
  Number of cores:                               32
  Total amount of constant memory:               65536 bytes
  Total amount of shared memory per block:       16384 bytes
  Total number of registers available per block: 8192
  Warp size:                                     32
  Maximum number of threads per block:           512
  Maximum sizes of each dimension of a block:    512 x 512 x 64
  Maximum sizes of each dimension of a grid:     65535 x 65535 x 1
  Maximum memory pitch:                          262144 bytes
  Texture alignment:                             256 bytes
  Clock rate:                                    1.40 GHz
  Concurrent copy and execution:                 Yes
  Run time limit on kernels:                     Yes
  Integrated:                                    No
  Support host page-locked memory mapping:       No
  Compute mode:                                  Default (multiple host threads can use this device simultaneously)

Test PASSED

Press ENTER to exit...





이 이상의 기술적 내용은 위키에 정리 ㄱㄱ.

'Tech' 카테고리의 다른 글

SICP 근황  (8) 2009.12.01
django 삽질  (3) 2009.11.19
CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Parameter vs Argument  (3) 2009.01.21
GEB: MU puzzle  (4) 2008.10.20
MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
Trackbacks 0 : Comments 2

Parameter vs Argument

Tech 2009.01.21 22:44
파라미터, 아규먼트 - 보통 구분하지 않고 사용하는 단어였다. 그런데 어제 SICP 스터디 소모임에서 누군가가 질문들 던졌다.

Parameter와 Argument의 차이가 뭐죠?

... 결국 위키에서 (나름) 깔끔하게 설명된 문서를 찾았다.

몇몇 문장만 뽑아서 대충 번역해보면,

A parameter represents a value that the procedure expects you to supply when you call it. The procedure's declaration defines its parameters.

Parameter는 당신이 프로시져를 호출할 때 함께 함께 주었으리라고 기대하는 값을 의미한다. 프로시져 선언에서 Parameter를 정의하게 된다.

An argument represents the value you supply to a procedure parameter when you call the procedure. The calling code supplies the arguments when it calls the procedure. The part of the procedure call that specifies the arguments is called the argument list.

Argument는 당신이 프로시져를 호출 할 때 Parameter에 전달하는 값을 의미한다. 호출하는 쪽의 코드에서 프로시져를 부를 때 Argument를 넘긴다. 프로시져 호출에서 Argument를 지정하는 부분을 Argument list라고 한다.

 In practice, distinguishing between the two terms is usually unnecessary in order to use them correctly or communicate their use to other programmers
실제적으로, 이 용어들을 구분하는 것은 올바른 사용이라던가 다른 프로그래머들에게 그 용도를 전달하는 것 등에 별로 필요하지 않다.

the words actual and formal can be used to distinguish between an argument and a parameter, respectively. For example, the equivalent terms actual argument and actual parameter may be used instead of argument; and formal argument and formal parameter may be used instead of parameter.

actual 과 formal 이라는 단어가 argument, parameter 를 구분하는데 쓰일 수 있다. 예를 들어, actual argument, actual parameter 라는 용어를 argument 대신 쓸 수 있다. 그리고 Formal argument, formal parameter 라는 단어를 parameter 대신 쓸 수 있다.


이정도 되겠다. 

요약하면, 함수 정의 등에서 넘어온 값을 받아서 함수 Scope 안에서 사용할 bound variable 을 파라미터(parameter, formal parameter, formal argument)라고 한다. 함수를 호출 할 때 함수 Scope 안에서 사용할 bound variable 에 넣어주세요 ~ 라고 주는 녀석들을 아규먼트(argument, actual argument, actual parameter) 라고 한다.

Caller의 눈으로 본 것이 Argument - Actual
Callee의 눈으로 본 것이 Parameter - Formal

번역할 때에는 파라미터 - 매개변수, 아규먼트 - 인수/인자/독립변수, 등으로 사용되는 듯 하다.

-----

후다닥 찾아본거라 잘못된 정보일 수 있으니, 오류가 있다면 가르쳐주세요 ~

'Tech' 카테고리의 다른 글

django 삽질  (3) 2009.11.19
CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Parameter vs Argument  (3) 2009.01.21
GEB: MU puzzle  (4) 2008.10.20
MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Trackbacks 1 : Comments 3

GEB: MU puzzle

Tech 2008.10.20 22:08
G.E.B. 에 나온 간단한 퍼즐. 더 읽기 전에 책에서 시킨대로 연습장에 끄적이며 좀 해봤다. 몇번 DAG을 그려보고 나서 "이건 안되는것 같은데?" 라는 생각이 들어서 증명, 혹은 납득할만한 설명을 만들어 보기 위해 고민. 음, 책을 더 읽기 전에 한번 써보고 넘어가고 싶음.

일단 규칙은, 이렇다.

처음, MI 라는 문자열를 가지고 있다.
  1. I가 포함된 문자열은 뒤에 U를 붙일 수 있다.
  2. Mx 형태의 문자열을 Mxx형태로 바꿀 수 있다.
  3. 문자열 안에 III 가 나오면 이를 U로 바꿀 수 있다. 반대 방향으로는 안된다.
  4. 문자열 안에 UU가 나오면 날려버릴 수 있다.
MU 를 만들 수 있겠는가?

MI -> MIU -> MIUIU -> ...
MI -> MII -> MIIII -> MUI -> ...

이런 식으로 가서 마지막에 MU 를 만들면 되는것인데... 불가능하다 - 고 생각한다. 왜 그렇게 생각하는지 한번 이 글을 읽는 당신을 납득시켜 보겠다.

문제의 constraint를 조금 느슨하게 바꾸어보자. 제약 조건이 더 약한 문제인데도 불가능하다면, 조건이 더 강한 문제는 당연히 불가능하다 - 자명하다. 자, 자, 문자열에 포함된 I의 갯수를 n 이라고 해보자.

시작할 때 n = 1 이다. n 은 0 보다 작아질 수 없다.

이건 자명하다. 그러면, 우리가 쓸 수 있는 규칙 4가지가 이 n을 어떻게 변화시키는지 보자.

1번 규칙: n -> n
2번 규칙: n -> 2n
3번 규칙: n -> n - 3
4번 규칙: n -> n

자, 조금 더 쉽게 바꾼 문제는 이렇다. n = 1 에서 시작해서 2를 곱하거나, 혹은 3을 빼는 것을 반복해서, n을 한번도 음수가 되지 않도록 유지하면서 n = 0 을 만들 수 있는가?

... 이렇게 바꾸면 바로 와닿지 않는다. 그래서 문제를 한번 더 바꿔 보았다. 이번에는 문자열 안에 있는 I의 갯수를 3 으로 나눈 나머지를 n 이라 해 보겠다. - 왜 하필 3인가? ... 어쨌든 마지막은 3을 빼서 n = 0 이 되어야 하므로(2를 곱해서 0을 만들려면 이전의 n=0이어야 한다 -_-) n은 반드시 3이 되어야 한다. 연쇄적으로 생각하면 일단 n 이 3의 배수가 되는 순간 0 을 만드는 방법은 자명해진다. 3을 계속 빼면 되니까. 그러니 3의 배수 만들기를 생각해본 것이다.

시작할 때 n = 1 이다, n 은 0, 1, 2 중 하나이다.

역시 이건 자명하다. 이제, n의 값을 각 규칙이 어떻게 바꾸는지 보자.

1번 규칙: (0, 1, 2) -> (0, 1, 2)
2번 규칙: (0, 1, 2) -> (0, 2, 1)
3번 규칙: (0, 1, 2) -> (0, 1, 2)
4번 규칙: (0, 1, 2) -> (0, 1, 2)

조금 더 이해가 쉽도록 중복을 제거하고 세로로 써볼까? 아래와 같은 두개의 mapping 이 가능하다.

0 -> 0
1 -> 1
2 -> 2

0 -> 0
1 -> 2
2 -> 1

이렇게 두 개의 mapping을 가지고 1을 0으로 보낼 수 있는가? 없다. 1, 2 사이에서만 왔다갔다 할 뿐. 즉, I 가 하나 포함되어 있는 문자열에서 I 가 3의 배수개(0, 3, 6, 9 ... 등) 들어있는 문자열은 만들어낼 수 없다는 것.

... 이정도면 스스로는 납득했음. 조금 더 formal 하게 쓰는 연습을 해도 좋겠지만 今日はここまで。

'Tech' 카테고리의 다른 글

CUDA Driver/Toolkit/SDK 설치하기 (Ubuntu 9.04 Jaunty)  (2) 2009.09.17
Parameter vs Argument  (3) 2009.01.21
GEB: MU puzzle  (4) 2008.10.20
MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Spiral number galaxy  (4) 2008.08.09
Trackbacks 0 : Comments 4

MySQL -> XML: CDATA Sanitize?

Tech 2008.09.26 13:14
필요한 일이 있어서 MySQL 에 있는 데이터를 XML로 덤프하는 파이썬 코드를 만들었다. 약 30줄 정도 되는 간단한 코드인데, 눈으로 보기에는 문제 없어보이는 XML 파일이 계속 well-formed xml 이 아니라고 하는거다. XML library 를 가져다가 validation을 하면서 만든게 아니라 그냥 데이터만 템플릿에 맞게 찍어주며 덤프한거라서 ... 그렇다고 덤프 코드에 validation을 넣기도 귀찮고 해서... -0-

  1. 문제가 되는 라인은 <![CDATA[ ... ]]> 을 가지고 있다.
  2. 한국어, 일본어, 중국어 등이 섞여있는 데이터를 쓴다.

두가지로 미루어 추정해본 결과 CDATA에 넣어준 데이터가 있어서는 안되는 것이라 생각. 원래 CDATA가 이스케이핑 하기도 뭐하고, 이래저래 처리하기 귀찮은 애들을 그냥 때려박을때 쓰는 용도라고 생각해서 별 생각 안했는데, 그래도 xml 이 markup language라서 문제가 있을 수도 있을 것 같다. 어쨌든 텍스트를 넣는 것이니 텍스트에 태그를 닫는 문자셋이 나오면 그걸로 방법 아닌가!? 생각해보니 문제가 생길 소지가 다분하네... =_=

그래서 웹서핑 결과 이런 페이지를 발견. ... 어째 내가 하려던 것과 꼭 같은 일을 먼저 해보신 분이 적어둔 것이라 신빙성 짱! 그리하야,

def acceptable_char(c):
    code = ord(c)
    if code == 0x09 or code == 0x0a or code == 0x0d or \
       (0x20 <= code and code <= 0xd7ff) or \
       (0xe000 <= code and code <= 0xfffd) or \
       (0x10000 <= code and code <= 0x10ffff):
        return True
    return False

... ... ...

# 1. remove CDATA finish tag
content = content.replace("]]>", "")
# 2. decode
content = content.decode("utf-8", "replace")
# 3. filter out unacceptable characters
content = filter(acceptable, content)
# 4. encode
content = content.encode("utf-8", "replace")

... ... ...

이렇게 CDATA 안에 들어갈 내용을 처리해 주었다. 크게 두가지 작업이다. 우연히 들어갔을지도 모르는 <![CDATA[ 에 매칭되는 닫는 태그가 있는 경우 날리기, 허용되는 unicode range 에 있는것만 남기기다.

이렇게 해결봤음. 아, 귀찮아... =_=

'Tech' 카테고리의 다른 글

Parameter vs Argument  (3) 2009.01.21
GEB: MU puzzle  (4) 2008.10.20
MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Spiral number galaxy  (4) 2008.08.09
투명 필름 문제(Scheme)  (4) 2008.08.01
Trackbacks 0 : Comments 2

하위 디렉토리에 있는 모든 .svn 을 날리는 법

Tech 2008.09.11 16:23
예전에 이거 한다고 몇줄짜리 스크립트를 만들었었는데 ... -_-; 오늘 다시 이거 할 일이 생겨서 잠깐 고민했더니 ...

find . -name .svn | xargs rm -rf

한줄 끝.

'Tech' 카테고리의 다른 글

GEB: MU puzzle  (4) 2008.10.20
MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Spiral number galaxy  (4) 2008.08.09
투명 필름 문제(Scheme)  (4) 2008.08.01
Statement vs Expression  (4) 2008.07.22
tags : .svn, rm -rf
Trackbacks 0 : Comments 5

Spiral number galaxy

Tech 2008.08.09 17:37
http://codingdojo.metaschool.org/5198
http://gall.dcinside.com/list.php?id=programming&no=84262&page=1&search_pos=-80935&k_type=1000

따라해봤음. ㅋㅋㅋ 나의 첫 curses 프로그램임 >_</ 재밌네 ~

import math
import time
import curses

def close_to_center(polar):
    return polar[0] < 1

def get_next_coord(polar):
    r = polar[0]
    theta = polar[1]
    r -= 0.2
    theta += (math.pi / 2.0) + 0.2
    return (r, theta)

def polar_to_euclid(polar):
    r = polar[0]
    theta = polar[1]
    return (int(r * math.cos(theta)), int(r * math.sin(theta)))

def draw(start, center):
    current = start
    i = 1
    while not close_to_center(current):
        pos = polar_to_euclid(current)
        stdscr.addstr(pos[1] + center[1], pos[0]*2 + center[0], "%s" % i, curses.A_NORMAL)
        current = get_next_coord(current)
        i += 1

if __name__ == '__main__':
    try:
        stdscr = curses.initscr()
        curses.noecho()
        curses.cbreak()
        stdscr.keypad(1)
        stdscr.timeout(0)
        r, theta = 0, 0

        while True:
            max_y, max_x = stdscr.getmaxyx()
            center = (max_x/2, max_y/2)
            r = min(center) - 1
            theta += 0.03

            stdscr.clear()
            draw((r, theta), center)
            stdscr.addstr(1, 1, "Ctrl-C to quit")
            time.sleep(0.005)
            stdscr.refresh()
    except KeyboardInterrupt:
        pass
    finally:
        stdscr.keypad(0)
        curses.echo()
        curses.nocbreak()
        curses.endwin()


뱅글뱅글

뱅글뱅글




'Tech' 카테고리의 다른 글

MySQL -> XML: CDATA Sanitize?  (2) 2008.09.26
하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Spiral number galaxy  (4) 2008.08.09
투명 필름 문제(Scheme)  (4) 2008.08.01
Statement vs Expression  (4) 2008.07.22
emacs: switch indentation  (0) 2008.07.18
Trackbacks 1 : Comments 4

투명 필름 문제(Scheme)

Tech 2008.08.01 08:44
코딩도장에서 풀고 있는 투명 필름 문제. UVA 에서 뽑아온 문제인데 ... 그쪽 스타일은 입출력이 귀찮아서 열심히 하기는 싫다. 그냥 내맘대로 문제를 줄여서(-_-a) scheme 으로 뚝딱. 아직 공부가 부족한가보다. ... 더 잘 할 수 있을텐데. 위키보다는 여기가 어울릴 것 같아서(문서가 아니라 코드!) 붙임. SICP 스타일로,

Representation 정하기
Selector 등 Abstraction layer 만들기
Logic 구현

의 순서를 밟았다. 실제로 Abstraction layer를 만들어둔게 디버깅 할때 꽤나 큰 도움이 되었다. <시작, 끝> 에서 시작이 끝보다 작은 필름의 경우 make-film을 고치는 것 만으로 해결된 것.

-----
(load "utility.scm")

; My film system!
(define (make-film s e t)
(if (> s e)
(list e s t)
(list s e t)))
(define (start-point film) (list 's (car film) (transparency film)))
(define (end-point film) (list 'e (cadr film) (transparency film)))
(define (start-point? point) (eq? 's (car point)))
(define (end-point? point) (eq? 'e (car point)))
(define (point-pos point) (cadr point))
(define (point-transparency point) (caddr point))
(define (transparency film) (caddr film))

; Test cases!
(define test-case-1 (list (make-film 2.0 9.0 0.9)
(make-film 4.0 13.5 0.7)
(make-film 7.0 17.0 0.8)))
(define test-case-2 (list (make-film 6.0 24.0 0.9)
(make-film 5.5 22.0 0.7)
(make-film 9.0 18.0 0.8)
(make-film 16.0 16.0 0.9)
(make-film 8.5 15.0 0.7)
(make-film 4.0 11.0 0.8)
(make-film 2.2 5.0 0.9)
(make-film 90.5 1.0 0.7)))
(define test-case-3 (list (make-film 1.0 2.0 0.5)
(make-film 1.0 3.0 0.5)
(make-film 2.0 3.0 0.5)))

; Main solver
(define (solve films)
; Input manager
(define (adjoin-point-list p l)
(cond ((null? l) (list p))
((< (point-pos p) (point-pos (car l))) (cons p l))
((or (> (point-pos p) (point-pos (car l))) (= (point-pos p) (point-pos (car l))))
(cons (car l)
(adjoin-point-list p (cdr l))))
(else
(error "Error!"))))

(define (make-point-list l)
(cond ((null? l) '())
((= (point-pos (start-point (car l))) (point-pos (end-point (car l))))
(make-point-list (cdr l))) ; for a vertical film
(else
(adjoin-point-list (start-point (car l))
(adjoin-point-list (end-point (car l))
(make-point-list (cdr l)))))))

(define expanded-input (make-point-list films)) ; This is the very input for main solver function

; Utility functions for main solver
(define (add-film cur-transparency added-transparency)
(* cur-transparency added-transparency))

(define (sub-film cur-transparency added-transparency)
(/ cur-transparency added-transparency))

; Main solver
(define (iter output before cur-trs remaining_input)
(let ((next-point (if (null? remaining_input)
'() ; It's not gonna be used
(car remaining_input))))
(if (null? remaining_input)
output
(iter (append output (list (list before (point-pos next-point) cur-trs)))
(point-pos next-point)
(if (start-point? next-point)
(add-film cur-trs (point-transparency next-point))
(sub-film cur-trs (point-transparency next-point)))
(cdr remaining_input)))))

; Direct output from main solver. It has some duplicates and useless info
(define raw-output (iter '() 0 1 expanded-input))

; Filter out some meaningless output element
(define output-filter
(lambda (sequence)
(filter (lambda (x)
(< (car x) (cadr x)))
sequence)))

; Combine(Reduce) some outputs for compact result
(define (combinable? x y)
(and (= (cadr x) (car y))
(= (caddr x) (caddr y))))

(define (combine x y)
(list (car x) (cadr y) (caddr x)))

(define output-reducer
(lambda (sequence)
(cond ((null? (cdr sequence)) sequence)
((combinable? (car sequence) (cadr sequence))
(cons
(combine (car sequence) (cadr sequence))
(cddr sequence)))
(else (cons
(car sequence)
(output-reducer (cdr sequence)))))))

; So, this is my final output!
(output-reducer (output-filter raw-output)))
-----

ordered-list 에 대한 일반적 구현을 만들어서 분리하면 코드가 확 줄어들 것 같다.

'Tech' 카테고리의 다른 글

하위 디렉토리에 있는 모든 .svn 을 날리는 법  (5) 2008.09.11
Spiral number galaxy  (4) 2008.08.09
투명 필름 문제(Scheme)  (4) 2008.08.01
Statement vs Expression  (4) 2008.07.22
emacs: switch indentation  (0) 2008.07.18
방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Trackbacks 0 : Comments 4

Statement vs Expression

Tech 2008.07.22 11:54
오늘 파이썬의 eval, exec 를 쓰다가 얼래? 라는 상황에 봉착했다.

C/C++ 에서는 대입문 - 이 사실 문(statement)이 아니라 식(expression)이다. 따라서 다음 코드가 동작한다.

#include <stdio.h>

int main() {
    int x = 10;
    printf("%d\n", x = 20);

    return 0;
}


실행하면 20 이란는 숫자가 콘솔에 찍힌다. 파이썬에서는 대입이 맞다. 따라서

print x=10


이런 파이썬 코드는 유효하지 않다. 별 생각 없이 쓰고 있었는데, 파이썬에 대해 아무것도 모르고 있었구나 -_-; ... 뿐 아니라 프로그래밍 언어 자체에 대해 기초가 부족했다. 아 뼈아퍼라...

사실, 문과 식을 구분해서 쓰는 사람이 그다지 많지는 않다(고 느낀다). 나도 가끔 필요할 때만 확인해보곤 하는데 ... 자, 정확히 statement, expression 이 무엇인지 설명한다면? 이라고 하니까 바로 답이 튀어나오지 않는다. 그래서 위키에서 긁어왔다.

In computer programming a statement can be thought of as the smallest standalone element of an imperative programming language. A program is formed by a sequence of one or more statements. A statement will have internal components (eg, expressions). - From wikipedia


An expression in a programming language is a combination of values, variables, operators, and functions that are interpreted (evaluated) according to the particular rules of precedence and of association for a particular programming language, which computes and then produces (returns, in a stateful environment) another value. The expression is said to evaluate to that value. As in mathematics, the expression is (or can be said to have) its evaluated value; the expression is a representation of that value. - From wikipedia

그냥 개인적인 생각이지만, 해보면 쉽다 쉽다 - 하는 함수형 언어를 사람들이 처음 접할때 많이 좌절하곤 하는데 그 이유가 이게 아닐까 한다. Imperative language에 익숙한 상황에서는 statement 의 나열로 문제를 해결하려고 하기 쉬운데, Functional language에서는 그게 쉽지 않다 - 기 보다는 제한적이거나 불가한 경우도 있다. 함수형 언어를 써보면 새로운 접근 방식을 익히게 된다고 하는데, 그 새로운 접근이 뭐냐? 라고 물으면 좀 난감했는데, 일단 이렇게 정리해볼 수 있으려나?

Expression oriented problem solving

Expression은 side-effect가 있을 수도 있고, 없을 수도 있다 - 고 한다. 이에 반해 Statement는 Side-effect를 만들어내기 위한 것이라고도 하는데 (statements do not return results and are executed solely for their side effects, - From wikipedia), side-effect를 지향/지양 하는 정도에 따라서도 접근이 달라질 수 있는 것 같다.

역시 기본부터 차근차근 다져야 하는데, 이런것도 확실히 정리 안해두고 코드를 만지고 있었다니 부끄럽다. :'( 일단 낙서 종료.

side-effect, referential transparency 등에 대해서도 살짝 정리해둬야겠다.

'Tech' 카테고리의 다른 글

Spiral number galaxy  (4) 2008.08.09
투명 필름 문제(Scheme)  (4) 2008.08.01
Statement vs Expression  (4) 2008.07.22
emacs: switch indentation  (0) 2008.07.18
방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
Trackbacks 0 : Comments 4

emacs: switch indentation

Tech 2008.07.18 10:33
위키에 남기기는 뭐한거라, 역시 까먹기 전에 정리.

나는, switch 문을 쓸 때 아래와 같은 들여쓰기를 사용한다.

switch (c) {
    case 1: blah blah ... ; break;
    case 2: blah blah ... ; break;
    default: blah blah ...; break;
}
아 그런데 emacs 이녀석이 나를 계속 괴롭히는거다. case 를 앞으로 붙여버리는데, set-label-offset 을 주면 된다길래 해봤는데 left-brace({)가 아래로 내려오면 되는데, switch 뒤에 붙어있으면 안됨. ... 한참을 구글링을 해서 겨우 찾았다.

(c-set-offset 'case-label '+)

으로 해결가능. cc-mode 도 필요하다고 하지만, 이건 emacs 20 이상에서는 기본이라고 하니 그냥 무시. 위 한 줄을 ~/.emacs.d/init.el 같은 곳에 넣어주면 된다. ;-)


'Tech' 카테고리의 다른 글

투명 필름 문제(Scheme)  (4) 2008.08.01
Statement vs Expression  (4) 2008.07.22
emacs: switch indentation  (0) 2008.07.18
방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
스팸폭탄 맞았음  (0) 2008.05.23
tags : C/C++, EMACS, indent, switch
Trackbacks 0 : Comments 0

방법당하다 by python-mysqldb 1.2.1_p2

Tech 2008.06.11 18:38
할일이 좀 있어서 python-mysqldb 모듈을 가지고 간단한 프로그램을 만들었다. 사용법은 참 간단했다.

import MySQLdb
db = MySQLdb.connect(host="localhost", user="deisys", db="deisys", passwd="xxxxxx")
cursor = db.cursor()

여기서부터는 cursor 를 가지고 놀면 된다. cursor.execute("show tables"), cursor.execute("create table test (id int)") 뭐 이런 식으로 ... 그래서 테스트를 위해서 엔트리 1억개를 insert 하는 코드를 만들었다. 대충 이런 모양이다.

 ...
 29 # Generate a bunch of (from, to) pairs and insert into the table
 30 values = []
 31 for x in xrange(0, VN):
 32     from = x
 33     digest.update(str(x))
 34     to = hash(digest.hexdigest()) % CN
 35     values.append( (from, to) )
 36     if from % CHUNK_SIZE == CHUNK_SIZE-1:
 37         query = "INSERT INTO info_test (from, to) VALUES " + ", ".join([str(x) for x in values])
 38         cursor.execute(query)
 39         values = [ ]
 ...

그런데... 몇분쯤은 걸리겠지 하는 생각에 엔터를 눌렀는데, 실행이 순식간에 끝난다. 엉? 엔트리 1억개를 넣는건데 1초도 안걸리다니, 요즘 DB가 졸 짱쎄졌구나! 라는 생각에 터미널 창에서 select * from info_test limit 1000; 을 때려 보았다.

mysql> select * from info_test limit 1000;
Empty set (0.00 sec)

mysql> _

엉? 뭐지? -_-; 그리고 삽질 시작. (cursor.close(), db.close() 도 밑에서 잘 해 주었다)

한시간쯤 뇌가 날아갔다가, 군것질을 하고 돌아오셨다. 그동안 몇몇 테스트를 해보면서 내린 결론은,

insert만 안된다

는 것. 왜 그럴까... insert는 쓰기 작업이고, 자주 일어나고, 연속적으로 일어나는 경우가 많으니까 아마도 어댑터가 나름 캐싱했을것 같은데 ... -> 빙고!

썅썅봐 -_-; db.close() 앞에 db.commit() 을 넣어주니까 제대로 들어간다. API에 보면,

commit(...)

Commits the current transaction


라고 달랑 한줄 나와있고, 나는 트랜잭션을 쓴 적이 없다. -_-; 아니 저게 없으면 방법당한다고 어디 한마디라도 써놓던가... ㅠㅠ 그리고 예의상(매너?) cursor.close() 나 db.close() 에서 들고 있는 캐시는 다 처리해 주어야 하는것 아님? -_-+

예전에 하둡님도 close 할때 flush 안해주셔서 초큼 난감했었는데, 이거 요즘 유행인가보다.

'Tech' 카테고리의 다른 글

Statement vs Expression  (4) 2008.07.22
emacs: switch indentation  (0) 2008.07.18
방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
스팸폭탄 맞았음  (0) 2008.05.23
Chunker's rolling out!  (3) 2008.03.27
Trackbacks 0 : Comments 5

Troubleshooting: apt-get update -> Dynamic MMap out of room

Tech 2008.06.05 12:11
얼마전, SenA를 방에 들고와서 데비안을 새로 깔았다. 근데 왠걸, repository에 testing, unstable을 추가하니까 apt-get update 중에 Dynamic MMap out of room 이라는 메시지가 튀어나오며 비정상 종료가 되는거다. ㅠㅠ 그래서 그냥 stable 만 쓰지 뭐 ~ 라면서 랄랄 거리고 있었는데, 오늘 우연히 발견.

apt-get update 을 하면 패키지 리스트를 가져오는데 이때 사용하는 캐시 크기에 제한이 걸려서 "너무 커욤" 이러면서 뻑났던것. 이전에는 diff 만 가져오면 되니까 상관 없었는데, 새로 설치하고 나서, 추가하니 처음에 가져올게 꽤 큰가보다.

데비안 머신에서 /etc/apt/apt.conf 를 고치거나, 이 파일이 없다면 만들어주면 된다.

APT::Cache-Limit 536870912;

이 한 줄을 넣어주면 된다. Cache limit은 바이트 단위이니 적당히 ... =_= 난 512MB 로 했다. 잘 되네 ;-)

'Tech' 카테고리의 다른 글

emacs: switch indentation  (0) 2008.07.18
방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
스팸폭탄 맞았음  (0) 2008.05.23
Chunker's rolling out!  (3) 2008.03.27
Hadoop 0.15.2 -> 0.17.0  (4) 2008.03.20
Trackbacks 0 : Comments 0

스팸폭탄 맞았음

Tech 2008.05.23 10:42
음... =_=

이전에 친구 블로그 덤프파일에서 스팸댓글(6천개쯤?)을 날려주는 스크립트를 만든적이 있다. 도저히 손으로 지울수는 없어서 블로그 덤프 내리고, 파싱해서 댓글 추출하고... 날릴 IP테이블 만들어서 뿅! 하는 거였는데... 그걸 이제 내 블로그 덤프에 쓰게 생겼구나.

라지만, 대충 보니 IP가 다양화? 된 것 같다. 이게 스팸인지 아닌지를 알아야 하는데, 그렇게 쉽진 않겠지. 몇달 전  스팸폭탄에서 뽑은 IP는 대충 600개 정도였다. 걔네들이랑 겹치는게 별로 없으면 낭패;; 오늘 저녁에 일단 내 블로그에 있는 스팸들 좀 가져다가 정리해보자... ㄷㄷㄷ

아놔-_-; 어떻게 막아야 할까나 -_-; 논문 하나 써볼까.


'Tech' 카테고리의 다른 글

방법당하다 by python-mysqldb 1.2.1_p2  (5) 2008.06.11
Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
스팸폭탄 맞았음  (0) 2008.05.23
Chunker's rolling out!  (3) 2008.03.27
Hadoop 0.15.2 -> 0.17.0  (4) 2008.03.20
Dokuwiki: latex plugin ...  (7) 2008.03.08
Trackbacks 2 : Comments 0

Chunker's rolling out!

Tech 2008.03.27 20:28
휴우... 빡센 한주가 가고 있다.

회사에서 틈만 나면 대통일 클러스터링이 어쩌고 저쩌고 하며 떠들던 우리 팀들, 드디어 두근거리는 가슴을 안고 잘라 봤는데... ㅎㄷㄷ 정말 생각대로 졸라짱 훌륭하게 잘라냈다. 그다지 큰 문서셋은 아니지만, 튜닝이고 뭐고 할 것 없이 거의 완벽하게 잘라내셔서 감동먹었다.

후후, chunker 주인 겸 visualizer 주인인 waityet도 결과가 너무 잘 나와서 물고있던 담배를 떨어뜨릴 정도로 놀라셨다고 한다.

결과는 이거(혹은 이거)지만, 이것만 봐선 모른다. 청크에 들어가는 페이지들이 놓고 봐야 감이 오는데... >_<=b

그나저나, 나는 ... ㅠ_ㅠ 타임어택 디버깅에 성공했지만, 실패라니 이 뭐 ... ... :'(

여튼, 회사일에서 감동먹게 해준 waityet에게 박수를! 고기먹자 ㅎㄷㄷ

...

하둡의 역습, 클론의 전쟁 등 수많은 어택이 있었지만, 저기까진 무사히 돌파... 뭐, 안된 것도 있지만 된 것도 있으니 이걸로 굿.

'Tech' 카테고리의 다른 글

Troubleshooting: apt-get update -> Dynamic MMap out of room  (0) 2008.06.05
스팸폭탄 맞았음  (0) 2008.05.23
Chunker's rolling out!  (3) 2008.03.27
Hadoop 0.15.2 -> 0.17.0  (4) 2008.03.20
Dokuwiki: latex plugin ...  (7) 2008.03.08
Nonnegative integers without numbers  (0) 2007.11.15
Trackbacks 0 : Comments 3

Hadoop 0.15.2 -> 0.17.0

Tech 2008.03.20 17:12
눈에 띄는 변화들:
  • HDFS에 권한 개념이 생겼다 !!! 직접 구현 해버릴까 하다가 말았었는데, 어휴 다행. 하지만 첨에 삽이 좀 있었따.
  • M/R에서 Map task/Reduce task 가 분리. 보여주는것만 다른건지는 확인해봐야 알듯.
  • 임시파일 이름에 Job name을 넣어버린다. -_-; 전에는 job name에다가 파일이름을 넣곤 했었는데, 파일 이름에 이걸 넣어버리니 방법당함. -_-; 아놔 .... ;;;

... HDFS 랑 M/R 구현은 좀 분리해줬으면 좋겠는데, ... -_-a

일단 Permission 구현이 들어간것 만으로도 장족의 발전이오!

'Tech' 카테고리의 다른 글

스팸폭탄 맞았음  (0) 2008.05.23
Chunker's rolling out!  (3) 2008.03.27
Hadoop 0.15.2 -> 0.17.0  (4) 2008.03.20
Dokuwiki: latex plugin ...  (7) 2008.03.08
Nonnegative integers without numbers  (0) 2007.11.15
ofstream redirect to stdout  (3) 2007.11.10
tags : change log, hadoop
Trackbacks 0 : Comments 4