Why ILP64?

전산 1975/04/23 00:32
yui 님의 질문에 이런 저런 댓글을 달려 시도해 보다 글이 너무 길어져 아예 새 포스팅으로 올립니다.

Win64 가 LLP64 를 선택했고 UNIX 진영은 LP64 를 선택한 와중에 어쩐지 Testors 혼자 ILP64 를 부르짖는 듯 하다. 내가 ILP64 를 지지하는 이유는 아주 간단하다. 왜냐하면 data type int"an integer, typically reflecting the natural size of integers on the host machine" 이어야 한다는 아주 단순한 생각 때문이다. 나는 ILP64 가 가지는 장점에 대한 생각을 하기 이전에 그저 직관으로 이 주장에 100% 동의한다.

LLP64 는 별로 다룰만한 가치를 느끼지 못하기 때문에 나는 LP64 가 ILP64 에 비해 가지는 장점에 대해 의견을 적는 식으로 썰을 풀어나가 보고자 한다. ILP64 대비 LP64 가 가지는 장점은 대충 3가지 정도로 요약된다. 1. 하위호환성 2. 공간/속도에 대한 비용 3. 32 비트 타입의 표준 문제.

우선, 이 심오한 주제를 이해하기 위해서는 "모두가 알고 있다고 생각하지만 64bit programming model 을 논할때는 마법처럼 잊어버리고 마는" C/C++의 '어떤 특성'을 다시 한번 상기시킬 필요가 있다. 아래 간단한 퀴즈를 하나 풀어보자. LP64 와 ILP64 환경에서 sizeof( temp ) 의 크기 차이는 얼마나 날까?

struct temp
{
    int    i;
    void* p;
};


LP64 환경이 4byte 적게 나올 것이라고? 땡~! 틀렸다. 두 환경에서 temp structure 의 크기는 같다. 이유는 64-bit machine 에서 byte-align 단위는 당연히 64-bit 이기 때문이다.


1. 기존 32bit 기반 코드들에 대한 하위호환성

노파심에 한가지 확실히 해두고 넘어가자면, Testors 는 void*intlong 으로 마음대로 변환할 수 있기때문에 ILP64 를 지지하는것이 절대 아니다. - 이런 코드를 만들어 내는 프로그래머는 정신을 차릴때까지 외딴 섬에 유배를 시켜야 한다 -

우선 서두에서 언급한 byte-align 특성 덕분에 만약 이전의 바이너리 데이터들을 #pragma pack() 매크로를 사용하지 않고서 저장해 놓았다면 안타깝게도 그것들은 새 플랫폼에서는 코드 수정없이 사용할 수 없다. 참고로 Testors 주변의 "거의 모든" 프로그래머들은 Network 패킷 전송에는 byte-align 을 1로 세팅하지만 파일을 저장할 때에는 byte-align 세팅을 하지 않더라. 인터넷을 뒤져서 structure 를 파일로 저장하는 코드를 몇개만 찾아보면 이해할 수 있을 것이다. 이것이 현실이다.

또다른 호환성 문제를 언급하기 전에 C 언어 표준화 원칙 중 한가지를 상기해 보자.

◆ 이전 명세와의 호환성을 유지한다.
프로그램이나 파일 형식이 하위 버전과의 호환성을 유지하는 것이 중요하듯이 프로그래밍 언어 역시 마찬가지다. 따라서 이전 명세의 표준을 따라 올바르게 작성된 프로그램은 새로운 명세에서도 거의 변화 없이 처음 의도된 행동을 보일 수 있도록 호환성을 유지하려고 노력한다.

주목해야 할점은 포인터 크기가 64 bit 로 늘어나는것을 절대 피할 수 없다는 사실이다. int 의크기를 유지 한다고 해서 기존의 코드를 다시 컴파일 하는 것만으로 새로운 환경에서 잘 돌아갈것이라고 생각한다면 오산이다. 포인터의 크기 변화로 인해 발생하는 코드 수정은 정말 엄청난 일이다. 이 변화는 위의 표준화 명세를 지킬 수 없을만큼 크다. 그렇다면 또다른 원칙 하나를 되뇌여 보자.

◆ 조용한 변화를 피한다.
새 기술이 도입되는 탓에 기존의 사소한 코드가 명시적인 오류를 일으킨다면 오히려 문제가 되지 않는다. 대개 컴파일러가 해당 오류의 위치와 원인까지도 적절히 지적해 줄 수 있기에 프로그래머가 조금만 수고를 들이면 이를 가볍게 수정할 수 있기 때문이다. 오히려 가장 위험한 것은 새 기술이 기존 코드의 의미를 조용히 바꾸어버리는 경우이다.

나는 sizeof( int )

그리고 어짜피 이 비용이 매우매우 크기 때문에, int 의 크기가 늘어나는 것을 수정하는 비용은 큰 의미를 가지지 않을 것이라 본다. 아마 대부분 그냥 놔두는 것만으로 잘 돌아갈 것이다. (물론 메모리를 좀 더 많이 사용할 것이다.) 어쨌든 이것은 기존 문자열 루틴들을 유니코드로 변경하게 수정하는 종류의 일보다는 훨씬 덜 고통스러운 일이라고 본다. 참고로 LP64 에서 플랫폼 변경에 따른 수정을 해야 한다면 간혹 void*int 에 보관하는 코드들 때문에 되려 ILP64 보다 더 큰 문제를 만나게 될 수도 있지 않을까? - 세상에는 지역변수의 주소를 리턴하는 함수를 작성하는 프로그래머도 있다는걸 명심하자. -

2. 공간/속도의 낭비

우선 공간의 문제부터.

우리 실생활의 현상을 다루는데 있어서 32-bit 는 아마 90% 정도의 경우에 이미 충분한 공간인것이 사실이다. 좋다. 그렇다면 이제부터 코드를 짤때 공간을 절약하고 싶다면 각 플랫폼에서 제공되는 32bit 의 자료형을 쓰면 된다.

기존의 코드가 돌아갈때 대략 1.5배의 메모리를 사용하는것은 어떻게 할것이냐고? 걱정말자. 기존의 메모리는 기껏해야 2G 정도의 메모리만을 사용할 수 있는 코드들이다. 내가 보장하는데 아마 3~4년 안에 당신의 데스크탑에는 지금 상상하기 힘들 정도의 메모리가 꽃혀 있을 것이다. 이전 32bit 기반 어플리케이션을 공간 최적화 하지 않은 버젼으로 수십개를 돌려도 메모리가 남을 만큼 말이다.


3. 32-bit 크기의 타입이 비표준이게 된다.

이 문제 때문에 8차선을 뚫을 수 있는 절호의 기회를 4차선으로 제한하느니 Testors 는 차라리 C/C++ 명세를 한번 업데이트 하자는데 한표를 던진다. 이참에 short 보다 약간 큰 prefix를 새로 하나 만드는게 어떨까? 아니면 long long 도 쓰자는 판에 (C99 에서 long long 은 이미 표준의 일부가 되었다.) 차라리 short short 를 16bit, short 를 32bit 로 만드는건 어떨런지.. -.- [...]
1975/04/23 00:32 1975/04/23 00:32

트랙백 주소 :: http://testors.net/tt/trackback/411