본문 바로가기

Programmer.cpp

Word Alignment 이야기

예전(2003년 쯤인가??)에 다른 사이트에서 적었던 글입니다..

글이 하나도 없으니 좀 휑~ 하기도 하고, 이런저런 참고 되실까 해서 자펌 합니다.

올리면서 지금 다시 읽어보니 엄청 꼼꼼했었군요 저도.. ㅎㅎ



 

안녕하세요.

우선, 글을 시작하기 전에 이 글은 이 전에 이미 언급 되었던 내용들입니다만, 보충을 요구하시는 분들도 계시고, 저도 나름대로 더 공유했으면 하는 내용들이 있어서 리바이벌을 하는겁니다.

재탕이 아니냐고 딴지 거시기 전에 이전 글들과의 차이점부터 파악을 해 주시기 바라며, 재탕 언급을 제외한 딴지들은 감사히 받겠습니다.

- 딴지 방지용 글은 이탤릭체로 요렇게 표기해 두었습니다. -

이미 Word Alignment가 어떻게 이루어지며, 어떠한 키워드를 통해 이루어 지는가에 대해서는 많은 분들이 언급을 해주셨기 때문에 이 글의 끝부분에서 간단히 정리만 하고 넘어가도록 하겠습니다.

이 글은 왜 Word Alignment가 사용되고, 어떠한 경우에 이를 제어해야하며, 어떠한 잇점을 가져다 줄 수 있는가에 촛점을 맞추었습니다.

 

1. Word Alignment는 무엇인가?

이 문제의 해답을 찾기 위해서는 우선 CPU가 어떻게 Data를 처리하는가? 라는 문제에서 출발을 해야겠습니다.

 

- 물론, CPU가 어떻게 프로그램을 수행하는가? 라고 질문을 바꾸시고 싶으신 분들이 계실지도 모르겠습니다만, 코드의 Word Alignment는 컴파일러가 고려해야할 대상이지 컴파일러를 이용해 프로그래밍을 하는 입장에서는 고려할 대상이 아니기 때문에 일단 고려대상에서 제외를 시키겠습니다. (이 부분은 컴파일러 관련서적이나 컴퓨터 아키텍쳐 관련서적에서 찾아보실 수 있습니다) -

 

Data는 저장장치에 위치하고 있습니다. 이것이 어떠한 Data이고, 어떠한 저장장치에 있던지 CPU가 Data에 접근하기 위해서는 이 Data가 Physical memory (편의상 이하 '메모리'로 부르겠습니다)에 위치해야하므로, Data는 어떠한 경로를 통했든, 현재 메모리 상에 존재하고 있다는 가정을 하나 두도록 합시다.

 Data를 CPU가 처리하기 위해서는 크게 메모리에서 버스를 통해 CPU내의 레지스터로 가져오게 됩니다. 마찬가지로, 처리 후에는 다시레지스터에서 버스를 통해 메모리로 보내지게 되죠.

 

- 캐쉬 메모리가 존재하는 시스템에서는 메모리를 캐쉬 메모리로 보셔도 좋습니다. 단, 이 경우에는 버스를 외부버스가 아닌 캐쉬메모리와 레지스터 간의 버스로 해석을 하시기 바랍니다. -

 

이 때, 버스라는 녀석은 빈차로 다니기를 꺼려하는 녀석이라 항상 자신이 옮길 수 있는 용량껏 옮기게 되며, 정해진 노선만 따른다는 사실을 놓치지 마셔야 합니다. 약간의 비유를 섞었습니다만, 다시 말씀드리자면...

버스가 n-bit 를 한꺼번에 운반할 수 있는 용량이라고 하면, 항상 메모리의 n의 배수 번지부터 n 비트의 데이터를 운반한다는 겁니다.

펜티엄의 경우를 예로들면 버스가 64bits 를 한꺼번에 운반할 수 있기 때문에 항상 8바이트 단위로 운반을 하며, 0, 8, 16... 번지를 기준으로 8바이트씩 운반을 하게 되는거죠.

그런데, 사용하고자 하는 데이터가 이 경계선을 물고 있다면 어떻게 될까요?

예를 들어, 펜터엄 시스템에서 4바이트짜리 데이터가 6번지에 위치하고 있다고 가정을 해봅시다.

이 데이터를 CPU에서 처리하기 위해서는 한번의 운반으로 레지스터로의 운반이 불가능합니다. 운반이 0번지, 8번지를 기준으로 이루어 지기 때문에 두 번의 운반을 통해서야 비로소 레지스터로 운반이 가능해 지기 때문이죠.

그래서, 컴파일러에서 이런 중복된 운반부담을 덜어주기 위해 버스의 크기에 맞도록 데이터들을 배치하게 되는데 이를 Data Alignment라 합니다.

 

- 펜티엄과 같은 경우에는 필요한 경우 두 번의 운반과정을 거쳐 데이터를 가져옵니다. 하지만, 일부 CPU들은 두번의 운반과정을 거쳐야 하는 경우에는 오동작을 일으키거나 처리를 못한다는 신호를 날려주도록 설계되어 있는 경우도 있습니다. -

 

'일반적인 경우'에 버스의 운반폭은 CPU의 레지스터(데이터를 담게되는 레지스터)의 크기에 맞춰지기 때문에 레지스터의 용량을 의미하는 단어인 'word'를 인용하여 'Word Alignment'라고 부르는 겁니다.

 

2. Word Alignment 옵션은 왜 필요한가?

앞서 살펴보았듯이 Word Alignment라는 것은 CPU의 데이터 버스 크기와 매우 밀접한 관계가 있습니다.

하지만, 세상에는 수 많은 종류의 CPU가 존재한다는 사실을 잊어서는 안됩니다.

또 한가지 잊지 말아야 할 것은 CPU가 무엇이건 상관없이 규격이 정해진 수 많은 데이터 형식(Data Format을 요기서만 문맥에 맞게 이렇게 적었습니다)이 존재한다는 것입니다.

상황이 이러하다보니 부득이하게 데이터 포멧에 맞추어 CPU의 데이터 버스에 촛점이 맞추어 제공되는 Word Alignment를 변경해야 하는 경우가 발생하게 되는 것입니다.

바이트 단위로 데이터를 처리하던 시절에 만들어진 데이터 포멧이 64비트 시스템이 유행인 요즘 시대까지 쓰이고 있는 경우는 흔히 볼 수 있습니다. 한마디로 Word Alignment가 고려되지 않은 데이터 포멧들을 처리해야 하는 경우가 발생할 수 있다는 이야기입니다.

따라서, 이러한 경우에는 부득이하게 Word Alignment를 변경해야 좋은 경우가 발생한다는 겁니다.

 

- 변경해야 하는...이 아니라 변경해야 좋은...입니다. Word Alignment가 아니더라도 수동 대입을 통해 해결이 가능하기 때문입니다. -

 

특히, 시스템간 소스 포팅을 하게될 경우에 자주 발생하며, 크로스 컴파일러에서는 이 옵션이 매우 자주 쓰이게 될지도 모릅니다.

 

- 크로스 컴파일러란 여러 타겟 머신을 가지는 컴파일러를 의미합니다. Visual C++도 펜티엄, Alpha, MIPS 등을 타겟 머신으로 가지는 크로스 컴파일러입니다. -

 

3. 어떠한 경우에 Word Alignment를 신경쓰게 되는가?

이 쯤 글을 읽으시고 이미 청사진이 그려지시는 분들도 계실겁니다.

가장 자주 고려해야할 경우는 하드웨어와 관련없는 데이터 포멧을 처리할 경우일 것입니다. 예를 들어, BMP 파일이 특정 CPU를 겨냥해서 만든 포멧이 아닌 이상 이 녀석을 처리할 때에도 Word Alignment를 신경써 주어야 한다는거죠.

그렇다면, 반대의 경우도 생각해 볼까요?

데이터 포멧을 사용하는 경우가 아니라 데이터 포멧을 설계하는 경우라면?

위에서 딴지 방지용 글까지 다 읽으신 분이라면, '잘못 잡아주면 안돌아가는 칩도 있다는데' 라는 걱정을 하시게 될지도 모릅니다.

다행히 어떤 시스템이든 뒤죽박죽의 데이터 포멧을 처리할 방법은 다 있기 마련입니다.

그렇다고 포멧을 설계하는데 이를 고려하지 않고 하는건 좀 무성의해 보이니까 Word Alignment를 고려한 포멧을 설계하는 것이 좋겠죠.

또 한가지 경우는 수행 성능을 위해서 Word Alignment를 고민해야 하는 경우가 있습니다.

작게는 하나의 데이터를 읽어올때를 신경써주어야 하는 경우부터, 덩치큰 데이터 포멧의 경우는 캐슁을 위한 페이징에서 데이터가 끊어지는 경우, 가상 메모리에서 페이지 폴트가 발생하는 경우까지 고려해야 하는 경우가 발생할 수도 있습니다.

그런 경우가 빈번히 발생하지는 않지만 있다는 사실을 알고있는것과 모르고 있는것의 차이는 분명히 있습니다.

 

4. Word Alignment를 이해하고 있다면 어떠한 잇점이 있는가?

가장 단순한 잇점이라면... 지식이 조금 늘었다는 것...이겠죠?

물론, 그것으로 끝나지는 않습니다.

일단, Word Alignment로 인한 피해를 줄일 수 있습니다. 굳이 피해라고 하기엔 뭣하지만 Word Alignment를 몰라서 파일로 부터 읽어온 데이터 포멧을 처리하지 못하게 되는 경우가 발생할 가능성이 충분히 있습니다.

특히, 포팅을 할 경우에는 시스템마다 다른 Word Alignment 방식때문에 소스를 뜯어고쳐야 하는 일도 발생합니다.

또, 시스템에 대한 이해에도 크게 도움이 될 것입니다.

원인을 알 수 없는 성능저하에 대한 대처방법도 한 가지 늘어나겠고,

미세하게나마 (어떤 경우에는 엄청난) 효율적인 프로그래밍이 가능해 질것입니다.

그 밖에도 좋은점은 찾아보면 있겠죠...

글쎄요...단점도 있을까요?

 

끝으로 Visual C++에서의 Zp 옵션과 #pragma pack 에 대한 사용방법...을 적었으면 좋겠지만...MSDN을 찾아보시길 권장하는 바입니다.

제가 방법에 대해 아무리 설명을 드리더라도 여러분 하드디스크에 깔려있는 MSDN의 설명보다 더 좋을 수는 없을테니까요...^^

 

그럼...즐거운 하루 되세요...