1. 성능과 알고리즘
(1) 현실의 퀵 정렬 알고리즘 구현체는 구간의 크기가 일정 기준 이하로 작아지면 그냥 O(n^2) 복잡도의 단순한 삽입 정렬로 대체하곤 한다. 그게 더 효율적이기 때문이다.
(2) 균형 잡힌 트리는 삽입, 탐색, 삭제가 모두 O(log n)의 복잡도로 되는 매우 유용한 자료구조이다. 그렇기 때문에 단순히 메모리 레벨의 set이나 map 컨테이너뿐만 아니라 파일 시스템이나 DB 같은 디스크 레벨에서도 쓰인다.
요즘 아무렇게나 DIR을 해도 파일 목록이 언제나 ABC 순으로 정렬되어 출력되는 이유는.. NTFS 파일 시스템이 내부적으로 이런 트리 구조를 사용하기 때문이다. (반면, 과거의 재래식 FAT는 연결 리스트 기반이어서 파일 목록의 정렬이 보장되지 않음)
단, 디스크 레벨에서는 단순한 이진 나무가 아니라, 이를 변형하여 한 노드에 딸린 자식이 좀 더 많은 B+ 같은 트리 구조가 쓰인다. 왜냐하면 디스크는 메모리보다 입출력 속도가 훨씬 더 느리며 랜덤 지점 탐색에 취약하기 때문이다.
그래서 한 노드 안에서 선형 검색을 좀 더 하더라도, 노드 하나를 탐색하고 읽는 횟수를 줄이는 게 더 이득이다. 다만, 이런 이념도 재래식 하드디스크가 아니라 플래시 메모리에서는 유효하지 않을 수 있다.
(3) 한 번에 한 스레드만 접근 가능해야 하는 코드가 있다면 보통 그 구간을 critical section이나 뮤텍스 따위로 둘러싼다.
그런데 이것도 "어? 다른 스레드가 이미 들어가 있네? 그럼 우리는 닥치고 바로 대기".. 이렇게 단순무식하게 하는 것보다,
loop을 돌면서 busy waiting, polling, spin lock을 n번만 더 시도해 보고 "그래도 여전히 다른 스레드가 나가지 않았으면 그때 대기 타자" 이런 유도리 전략이 좀 더 효율적일 때가 있다.
왜? 대기를 탔다가 깨어나는 작업 자체가 사용자 모드에서 커널 모드로 들어갔다가 나오는 것이며, 수천 사이클에 달하는 CPU 오버헤드를 요구하기 때문이다. 대기하고 있는 스레드는 CPU를 먹지 않지만, 대기 상태로 들어가거나 깨어나는 출입 과정은 공짜가 아닌 것이다.
더구나 요즘 컴퓨터는 코어가 여럿 있기 때문에 한 스레드에서 아주 잠깐 무식한 busy waiting을 하더라도 그게 타 스레드의 실행 성능에 영향을 주지 않는다. 그럴수록 대기 진입을 한 템포 늦춰서 신중하게 하는 게 가성비가 더 커진다.
일상 생활에다 비유하자면, 여러 잡다한 물건을 들고 있어서 무거운 채로 엘리베이터나 버스를 기다리는 것과 비슷하다. 이걸 바닥에 완전히 내려놓아 버렸다면 팔이 힘들지는 않지만, 그걸 다시 집어드는 것도 굉장히 번거로운 일이 된다. 그러니 버스나 엘리베이터가 수 초 안으로 금방 온다면 그냥 그 물건들을 들고 기다리고 있는 게 더 낫다.
이렇듯, 컴퓨터에서는 성능을 최대화하기 위해 한 방법만으로 만족하지 않고, 상황에 따라.. 특히 아주 제한된 문맥에서는 통상적으로 비효율적이라고 알려진 무식한 방법까지도 동원한다는 걸 알 수 있다. 스타로 치면 여러 유닛을 조합하는 것과 같다.
2. 자원의 회수
식물은 죽어서 말라 비틀어진 잎· 줄기나 썩은 열매 따위의 처리가 아주 간편한 축에 든다. 땅에 파묻기만 하면 거름이 되고 도로 자연으로 돌아가고 구성 물질이 회수된다.
뭐, 동물도 궁극적으로 그렇게 되기는 한다. 하지만 사체가 분해되는 과정이 식물보다 훨씬 더 더럽고 끔찍하고 더 오래 걸리는 편이다.
이런 물질의 순환은 뭔가.. 가상 머신에서 GC에 의해 자동 관리되는 메모리 같다는 생각이 들지 않는지?
본격적으로 물질의 메모리 누수가 문제되기 시작한 건 인류가 자연이 제대로 감당하지 못하는 플라스틱 같은 고분자 화합물을 만들어서 쓰기 시작하고부터이다. 그리고 반감기가 끔찍하게 긴 방사능 물질도 이런 범주에 든다고 볼 수 있겠다.
뭐, 썩지 않는 물질이 다 문제이고 골칫거리는 아니다. 수도관 같은 건 절대로 부식되거나 썩지 않는 재료로 만들어서 수백, 수천 년은 써야 할 테니 말이다.
3. 코드
(1) 우리나라의 모든 법조문들이 몽땅 github에 올라오고, 전체 개정 이력을 Show log 명령을 통해서 조회하고 싶다는 생각이 든다. 전철 노선도 같은 물건도 마찬가지이다.
(2) 대학교 컴터공학과 학부에서 시스템 프로그래밍 시간에 MIPS 어셈블리어 갖고 깨작깨작 실습하는 건.. 육사에서 승마나 백병전 총검술 잠깐 맛보기 하는 것과 정확하게 대응하지 싶다~ ㅋㅋㅋ
학교에서 뭔가 C/C++, Java, Python 같은 실용적인(?) 언어 말고 뭔가 비현실적인 언어를 다뤄 보는 게 이렇게 어셈블리어 같은 레거시 계열, 아니면 엄청나게 순수한 이론 이상을 추구하는 함수형 언어 계열.. 이렇게 둘로 나뉘는 듯하다.
(3) 자동차 취급설명서는 소스 코드 곳곳에 들어서 있는 조건부 컴파일의 완벽한 예시로 보인다. * 표시가 돼 있는 각종 선택사양들.. 그리고 악보의 음표 위에 붙은 각종 나타냄말? 스타카토, 스타카티시모 이런 건 매크로의 예시이다.
악보는 각종 반복과 분기가 복잡하게 꼬이면 흐름이 진짜로 어지간한 프로그램 코드처럼 바뀌기도 한다.
(4) 성경에서 '주의 책', '(어린양의) 생명책' 같은 상상 속의 거대한 책이 언급된 걸 보면.. 예수 믿는 컴터쟁이들은 하늘나라에 있는 거대한 데이터베이스와 DB 서버 정도는 떠올릴 수 있을 것 같다.
물론 인간이 만든 컴퓨터는 신의 주요 성품 중 하나인 '무한, 영원'이라는 걸 절대로 구현하지 못하는 물건이다. 그러니 DB 드립은 마치 "김 성모 스타일의 성경 이야기"만큼이나 그냥 웃자고 늘어놓는 말일 뿐이다.
(5) 요한복음의 마지막 구절인 "이 세상이라도 예수님의 행적을 기록한 책들을 다 담지 못할 것이다"는 정보량과 관련된 언급이다. 그리고 삼손의 수수께끼 놀이는 정보 보호· 보안과 관련된 통찰을 주는 이야기이다.
4. 자동과 수동
요즘 수동 변속기 차량을 몰 줄 아는 사람이 갈수록 드물어지듯, 컴터 업계도 C/C++처럼 메모리를 수동으로 관리하는 저급 언어를 제대로 다룰 줄 아는 사람이 갈수록 드물어지는 것 같다.
직장에서 부사수로 들어온 어린 신입 개발자에게 사수가 메모리 leak이라는 개념을 알려주는 게 굉장히 뜻밖이고 놀라워 보였다.
하긴, 공대 1학년의 기초 필수 프로그래밍 과목에서 가르치는 언어도 초창기엔 C/파스칼이다가 나중에 Java를 거쳐 지금은 파이썬이지 않은가. 프로그래밍을 위한 전산학적인 소양하고, C나 컴퓨터 특유의 지저분한 감각이랄까, 이 둘이 영역이 완전히 일치하지는 않기 때문이다.
고깃집의 경우, 직원이 알아서 고기를 다 썰고 구워 주는 곳은 자동 변속기-_- 같고, 손님이 직접 고기를 얹고 굽고 자르고 뒤집어야 하는 곳은 수동=_=;;에 해당된다. 후자보다는 전자가 아무래도 마음 편하게 고기를 먹을 수 있지만.. 인건비가 추가되어 고기값이 더 비쌀 것이다.
5. 전체 리셋
컴퓨터 시스템을 날리는 방법으로 sudo rm -rf 라든가=_= Windows의 레지스트리 날리기, 시스템 디렉터리 날리기 같은 게 있다.
운영체제가 아닌 DB에서는 delete * 내지 drop table 같은 파괴적인 쿼리가 있다. 손가락 까딱 잘못 건드려서 회사 재산과 관련된 DB를 날렸다간 짤리는 정도를 넘어 손해 배상 소송을 당할 수도 있을 것이다.
그런데 국가로 치면.. 헌법 제1조가 바뀌거나 날아가는 게 그런 급의 파괴적인 사건일 것이다. 헌정 체제가 쿠데타로 인해 싹 뒤집히거나, 아니면 전쟁에서 지기라도 해서 외적이 자국 행정부를 완전히 접수했을 때에나 있을 수 있는 일이다.
우리나라의 경우, 옛날에는 "대한민국은 민주공화국이다" 같은 몇몇 조항은 개헌조차 아예 영원히 불가능한 조항으로 못 박으려는 시도가 있었다. 컴퓨터로 치면 운영체제의 작동과 직접적인 관련이 있는 일부 시스템 파일을 절대 변조· 삭제할 수 없게 특수하게 보호하는 것과 비슷하다고 하겠다(업데이트 받을 때만 빼고).
하지만 법리적으로 볼 때 그렇게까지 할 필요는 없기 때문에 개헌 불가 조항 같은 건 과거의 해프닝으로 끝났다. 그리고 지금 6공화국 헌법은 그렇잖아도 개헌이 너무 어려운 형태가 된 감이 좀 있다.;; 과거에 널뛰기 하듯이 수시로 개헌하던 관행을 없애고 싶었던 심정은 이해가 가지만 지금은 그것 때문에 미래까지 발목이 잡힌 것 같다.
6. C++ export와 우주왕복선
2000년대 초에.. EDG 같은 일부 C++ 컴파일러 개발사에서는 희대의 흑역사 표준 기능이던 export를 구현하느라 상상을 초월하는 삽질을 했던 거랑,
NASA에서 2003년의 컬럼비아 우주왕복선 사고 이후에 이제는 우주왕복선을 띄울 때마다 옆에 구조용 예비 기체까지 같이 대기시키면서 정말 눈물겨운 삽질을 잠시 했던 것..
둘이 시기도 비슷하고 심상이 뭔가 묘하게 비슷하게 느껴진다.
전자는 지금까지 C++ 표준에 새로 추가되었던 복잡한 기능들과는 구현 난이도가 차원이 달랐다. 기존 언어 구조의 근간을 다 뒤엎어야 하는 헬 수준이었는데, 그렇다고 템플릿의 모듈화를 제대로 실현해 주는 것도 아니었다. 이건 정말 백해무익에 가까운 미친 짓이었다. 결국 export는 2010년대 C++11에서는 완전히 삭제되었다.
우주왕복선에다가 구조 미션까지 추가한 것 역시.. 셔틀 한 대에다가 사람을 11명이나 태우는 것(기존 승무원 7 + 구조 요원 4), 안 그래도 3대밖에 없는 셔틀을 매번 2대나 세팅해야 하는 것, 묘기에 가까운 어렵고 위험한 기동으로 조난 당한 셔틀에 접근해서 사람을 구조하는 것..
살인적인 비용 대비 사람을 살릴 가능성도 별로 없는 미친 짓이었다. 다행히 이 미션이 실전에서 쓰인 적은 없었으며, 우주왕복선 역시 C++11과 비슷한 시기인 2011년에 완전히 퇴역했다.
7. 나머지
(1) 생물은 번식할 때 동물과 식물을 막론하고 가까운 혈통끼리 교배하지 말고, 최대한 먼 촌수끼리 다양하게 섞여서 교배해야 유전병 없이 건강한 후세가 태어나고 안전하다고 여겨진다. 유전적 다양성이란 게 중요하다.
이런 걸 뭔가 숫자의 특성으로 표현하면 해시값의 충돌이 안 나는 것, 셸 정렬이 빠르게 수행되는 간격 수열을 구하는 것(무식하게 2^n에서 절반씩 줄이는 건 최악), 퀵 정렬의 pivot 중간값을 적절하게 잘 고르는 것에 대응하는 것 같다.
(2) 자동차나 자전거 운전하다가 상대방과 부딪칠 것 같아서 한쪽으로 피하는데..
골때리게도 상대방도 내가 피하는 방향과 같은 방향으로 피하고, 이 상황을 탈피하지 못해서 결국 부딪히는 경우가 있을 수 있다.
이런 게 머신러닝이나 방정식 근 찾기에다 비유하자면 처음에 시작점을 잘못 잡고 학습을 잘못 시켜서 최적해로 수렴을 못 하고 삼천포로 빠진 것과 비슷해 보이는 상황이다. 아니면 데드락을 극복하지 못했거나.;;.
(3) 옛날, 1955년쯤에 중공의 마오 주석께서는 하늘을 향해 삿대질을 하며 "저 새는 해로운 새.." 아니, "참새는 해로운 새"라고 교시하시였다는데..
1968년쯤에 네덜란드의 전산학자 다익스트라는 ACM 저널을 통해 "GOTO Considered Harmful".. 즉, 스파게티 코딩이 해롭다고 저격했었다. 오늘날은 저 두 말투가 모두 밈..처럼 쓰이고 있다. ㅋㅋㅋ
Posted by 사무엘