지난번에는 압축시 한번은 생각해 볼 압축 비밀번호와 유니코드 파일이름에 대해 이야기 했습니다.
이번에는 압축 프로그램을 좀 더 효율적으로 사용하기 위한 정보를 올려봅니다.

저는 압축 프로그램의 기본적인 성능측정 잣대를 5가지로 봅니다.
  1. 압축 후 얼마나 작게 만들어주는가
  2. 압축시 걸리는 시간
  3. 해제시 걸리는 시간
  4. 압축시 필요한 메모리 크기
  5. 해제시 필요한 메모리 크기
위 요소 중에서 사용자들이 가장 체감적으로 느끼는 것은 1,2, (3) 입니다. 그래서 이번 글에서는 1,2,3번에 중점을 두어 압축프로그램들의 벤치마크를 하고, 요즘 사용되는 멀티코어와 대용량의 메모리를 가지는 시스템과의 연관성에 대한 결과를 살펴 보도록 하겠습니다.

테스트 한 예제 파일
  1. 다량의 그림파일과 압축파일이 들어있는 1.31GB(1412160010)의 어느 홈페이지
  2. Google Earth for OSX, Gimp 2.6.8 source code, Maximum Compression사이트의 full_testset테스트파일, 제가 수정한 CleanArchiver 프로그램이 들어있는 약400MB(416703838) 테스트셋
우선 위 파일들은 각각 중복성을 가지게 하기 위해서 내부에 자신의 사본을 2벌씩 가지게 했습니다. 이후 솔리드 압축에서 결과의 차이를 볼 수 있습니다. 그리고 1번 테스트셋은 압축이 이미 거의 된 결과물이고 2번은 압축이 매우 잘 되는 파일이 많이 들어 있어서 테스트 후 결과를 비교하기 위해 설정했습니다.

테스트는 4GB메모리에 쿼드코어 제온 E5355 이 2개 들어가 있고 Windows 2003 R2 x86버전이 설치된 시스템을 사용했습니다. 아쉽게도 64비트 운영체제가 없어서 64비트일때의 차이는 테스트에 고려할 수 없었습니다. 그리고 7zip의 일부 압축률에서의 테스트는 압축시 필요로 하는 총 메모리의 부족으로 테스트 할 수 없었습니다.

테스트에 이용한 압축 프로그램들과 이용한 포멧의 종류는 아래와 같습니다.
일부 생소한 압축 프로그램이 등장하는데요, 결과에서 좋은 정보를 드리기 위해서 추가했습니다. nanozip은 LZPF, LZHD 알고즘을 사용했고, quad, balz는 ROLZ알고리즘을 사용합니다.

그 이외에는 각각의 프로그램들에서 주로 내세우는 압축 포멧을 이용해서 벤치마크에 사용했습니다. 테스트시 사용한 스크립트는 4NT에서 타이머 함수를 가지고 측정했으며 첨부파일을 받아서 직접 해 보실수 있습니다. balz와 quad는 단일파일 압축만 지원하기 때문에 디렉토리 결과를 파악시 7z의 tarball을 이용해 묶은 시간을 벤치마크에 포함했습니다.

이제 본격적으로 벤치마크 결과에 대해서 살펴보도록 하겠습니다. 테스트 결과 택스트 파일을 올립니다.

아래 그래프들은 위 첨부 데이터 중 멀티쓰레드가 모두 가능한 기본적인 시스템 상황에서 각 압축프로그램들의 기본 설정사항에서 압축률만 옵션으로 변화를 주어 압축한 결과를 나타낸 것입니다. 단, 7-zip의 bzip2 알고리즘을 이용한 경우는 보통 압축률에 쓰레드 갯수를 1,2,4,8개로 한 결과입니다. nanozip은 LZPF,LZPF_large, LZHD, LZHDS알고리즘을 지정하고 각각의 결과를 함께 나타냈습니다. 그리고 2번 테스트셋을 하나의 tarball로 묶은 후 그것을 같은 방식으로 압축한 결과를 원래의 2번 테스트셋과 비교하기 위해서 3번째 그래프로 올립니다.

그림의 순서는 압축과 해제결과 각각 차례대로 1번 테스트셋, 2번 테스트셋, 2번 테스트셋의 묶음파일입니다. 각각의 그림은 클릭하면 크게 볼 수 있습니다.

다음은 압축시 걸린 시간과 압축결과 파일 크기의 그래프입니다.
1번 테스트셋 종합 압축결과 1번 테스트셋 종합 압축결과
2번 테스트셋 종합 압축결과 2번 테스트셋 종합 압축결과
2번 싱글 테스트셋 종합 압축결과 2번 싱글 테스트셋 종합 압축결과


다음은 해제시 걸린 시간과 압축결과 파일 크기의 그래프입니다.
1번 테스트셋 종합 해제결과 1번 테스트셋 종합 해제결과
2번 테스트셋 종합 해제결과 2번 테스트셋 종합 해제결과
2번 싱글 테스트셋 종합 해제결과 2번 싱글 테스트셋 종합 해제결과
그림에서 가로축은 압축 또는 해제시에 걸린 시간을 나타내고 세로축은 압축한 결과의 크기가 원래보다 몇퍼센트인지를 보여줍니다. 즉 왼쪽 아래 원점에 가까워질수록 높은 압축률 및 좋은 압축&해제 시간을 보이는 것입니다.

위 그림들을 보고 참고할 사항을 나열해보면
  • 솔리드 압축을 이용할 경우 솔리드 블럭 설정이 매우 중요합니다. 이를 너무 작게 잡으면(압축률을 작게 설정시 해당됨) 압축도 잘 되지 않을뿐만 아니라 압축 시간도 많이 걸리게 됩니다.
  • 압축률을 압축프로그램에서 선택시 가급적 '보통'을 선택하는게 시간&용량면에서 평균적으로 유리합니다.가급적 나머지 압축률은 사용하지 말고 '보통'을 주로 사용하시기 바랍니다.
  • 7zip의 경우 솔리드 압축을 사용하기를 적극 권장(실제 기본으로 켜져있음)하며 4개이상의 멀티코어와 3GB이상의 큰 메모리를 가지는 시스템에서는 LZMA2 알고리즘을 이용할 경우 큰 압축&해제시간 향상을 꾀할 수 있습니다. 압축 해제시 LZMA알고리즘보다 훨씬 빠르기 때문에 LZMA2알고리즘 사용을 적극 권장합니다.
  • rar의 경우 적당한 압축효율과 상대적으로 낮은 압축&해제 시간을 가지는 포멧인 것이 나타납니다. 역시 멀티코어의 이득을 보기 때문에 코어가 많을수록 좋은 결과를 보여줍니다. 여기서 나타나지는 않았지만 한가지 장점은 좋은 결과에도 불구하고 적은 메모리를 사용합니다.제가 언급한 성능 고려요소 5가지 부문에서 종합 1위를 준다면 Winrar에게 줄 수 있겠네요. rar도 7-zip과 마찬가지로 압축파일에 추가 수정을 하지 않는다면 솔리드 압축시 시간 손실 거의 없이 용량의 이득을 볼 수 있으므로 권장합니다.
  • 알집의 alz는 압축시 zip의 일반적인 성능을 가지지만, 해제시 일반 zip보다 2배정도 빠른 속도를 가지고 있습니다.
  • 알집의 새로운 포멧인 egg는 압축 & 해제 시간과 압축효율면에서 7zip의 알고리즘을 사용했음에도 불구하고 7zip보다도 쳐지는 모습을 보여주고 있습니다. 흥미로운 점은 egg의 경우 '최적옵션'을 선택시 알집 스스로 자신이 zip의 deflate와 유사한 알고리즘 혹은 LZMA와 유사한 것을 고르게 되는데 아쉽게도 결과는 둘 다 모두 좋지는 않습니다.
  • quad, balz는 멀티쓰레드를 사용하지 않고 rar와 같이 작은 메모리를 사용함에도 불구하고 중상위권에 속하는 좋은 압축률과 압축&해제 시간을 기록했습니다. 거기에 보테어 기본적으로 솔리드 옵션이 없지만 중복된 파일을 모두 하나로 압축해 주었습니다.
  • nanozip은 정말 경이적인 속도와 압축률을 보여줍니다. quad, balz와 같이 멀티쓰레드를 이용하지 않지만 LZPF & LZPF_large의 경우 최상의 압축률과 압축 속도를 보여주어서 nanozip의 귀추가 주목됩니다. 메모리 사용량의 경우 기본적으로 400MB를 압축시 사용하지만 이정도의 성능 향상은 기적이라 할 수 있습니다.

7zip과 rar의 멀티쓰레드 갯수별 결과 그래프가 있는데, 결론을 말하고 생략하겠습니다.
7zip의 LZMA알고리즘은 딱 2개의 쓰레드가 동시에 돌아가면 됩니다. 적으면 큰 성능하락을, 많으면 2개와 별차이가 없습니다.그런 이유로 4개 이상의 멀티코어의 능력을 이용하기 위해서는 LZMA2알고리즘을 반드시 사용해야 합니다. 그리고 압축 해제시에는 언급한데로 LZMA보다 LZMA2가 2배 가까이 빠르며 LZMA와 마찬가지로 쓰레드 갯수에는 영향을 받지 않습니다.

rar도 압축해제시에는 멀티쓰레드의 영향을 받지 않습니다. LZMA2 및 rar 의 경우 4개에서 8개의 쓰레드로 동시에 압축하는 성능 향상은 2개에서 4개의 차이보다 크지 않습니다. 즉 성능 향상은 로그함수적으로 올라갑니다.

pbzip2의 경우는 이와는 달리 쓰레드 갯수=압축성능향상의 비례가 1:1 정비례에 보다 비슷하게 성립합니다. pbzip2해제시에는 멀티쓰레드의 영향은 받지만 압축보다 크지는 않습니다.

위 그림을 비교해보면 얻을 정보가 더 많지만 용두사미로 끝이 나고 말았네요 : )
그래프를 꼼꼼히 비교해서 살펴보시면 많은 정보를 얻을 수 있습니다. 결과 수치를 텍스트 파일로 보면 좀 더 많은 정보를 얻을 수 있지만 그건 추천하지는 않겠습니다.

참고 링크로 Teddy Rogers라는 유저가 Tuts4You.com 에 올린 LZMA vs LZMA2 vs WinRAR64라는 압축 비교 문서를 첨부파일로 올립니다. 문서에는 4코어 CPU를 가진 컴퓨터를 가지고 압축 프로그램에서 사용하는 쓰레드 갯수를 바꿔가면서 실제 CPU사용 현황 및 메모리 사용량 등을 대략 쉽게 보여주기에 제가 벤치마크한 것과 비교하면 좀 더 이해에 도움이 될 듯 합니다.

COLLAGE FACTORY 님의 7-zip 이야기는 압축 알고리즘에 대한 재미있는 내용이 있으니 관심 있으면 읽어보세요.

다른 의견이나 반대의견 또는 하시고 싶은 말씀이 있다면 자유롭게 남겨주시기 바랍니다.
Posted by trip2me
,
SourceForge에 있는 Keka라는 OSX을 위한  p7zip GUI 프론트엔드 프로그램 버그에 이런 저런 글을 달면서 윈도우에서 기본 압축 프로그램으로 .zip 압축을 할 때 적용되는 몇가지 사항에 대해서 제대로 알게 되었다.
  1. 압축 파일 내부의 파일이름은 현재 시스템의 OEM코드페이지의 문자를 사용한다.
  2. 압축 파일에 암호를 걸면 암호는 현재 시스템의 OEM코드페이지에 한쌍으로 연관된 ANSI 코드페이지 문자열을 사용한다.
.zip 압축은 만들어진지 오래된 압축포멧이다. 하지만 ISO정도의 국제 공인 표준이 아닌 PKWare에서 관리하는 AppNote정도의 De Facto표준이기에 이런저런 회사의 개별 구현들이 표준에 들어가 플랫폼간 파일 교류에 문제를 일으키게 한다.

 첫번째 항목은 예전 DOS시절에 사용하던 zip압축의 파일명 저장 방식때문에 일어난다. 실제 zip 포멧을 처음 만들었을 때는 유니코드와 같은 전세계 문자가 들어있는 파일명을 고려하지 않았다. 사실 유니코드와 같은 다국어 지원에 대한 지원을 그 당시로서는 고려하지 않았다. 그 대신에 각각의 언어환경에서는 각자의 문자셋이 있는 코드페이지로 압축파일 저장을 했다. 그래서 압축 파일안에 있는 파일명이 무슨 문자셋으로 인코딩이 되어있는지  정보가 들어있지 않아서 다른 외국어 윈도우 사용자가 압축을 풀려고 시도를 하면 이상하게 깨어저 보이게 된다.

 현재 사용하는 윈도우들은 유니코드를 모두 지원하지만 하위호환성을 염두에 둔 이유인지 AppNote에 UTF-8 파일명을 사용하는 플래그를 아직까지도 지원하지 않고 있어서 사용자들에게 불편을 주고 있다. 그나마 다행인 것은 요즘 나오는 써드파티 압축 프로그램들에서 유니코드 지원을 위해서 UTF-8 플래그를 인식하게 해 주도록 업데이트 되고 있는 상황이다.

 그리고 OSX나 요즘의 Linux의 경우 파일처리 시스템 콜에서 UTF-8을 파일이름 전달에 기본적으로 사용하게 되어 상황이 좋아졌는데, OSX의 경우 한가지 문제는 압축파일에 UTF-8 파일명을 사용한다는 플래그를 전혀 세팅하지 않아서 유니코드를 지원하는 프로그램들이 제대로 인식하지 못한다는 사실이다.( 윈도우의 기본 압축 프로그램이 하는 행동처럼 아마 자신들만 사용하는 로컬 문자셋이라고 생각하는 모양이다.)  또다른 문제아닌 문제는 OSX에서는 기본적으로 일부 풀어쓰기 영역의 유니코드문자로 표현하는 언어(한글,라틴어,...)가 그 상태 그대로 압축파일에 저장되기에 이 파일을 윈도우나 리눅스에서 풀게되면 보통 사용하는 NFC정규형으로 되지 않아 있기에 이런저런 사소한 불편함이 따른다는 것이다. 아직까지 파일이름의 정규화에 대해서는 AppNote에도 고려가 되어 있지 않고 사실 어떻게 보면 압축 포멧 자체에서 고려할 사항이 아닌 부분이다. 하지만 실제 불편함이 일어나기에 어느정도 정규화 변환 정도의 옵션은 압축 프로그램에서 제공해 주어야 하지 않을까 하는 생각이 든다.

 첫번째 위의 이유로 인해서 윈도우에서 아래 언어를 사용하는 로케일은 ANSI/OEM 코드페이지가 없기 때문에 유니코드로 지원하지 않는 윈도우의 기본 zip압축을 가지고서 자신의 언어로 이루어진 파일명을 압축파일안에 사용하지 못한다. 그래서 IT가 발전하는 인도에서는 도대체 자신들의 컴퓨터에 저장하는 파일 이름을 영어로만 저장하고 압축하는지 참으로 궁금하다. 이것과는 직접적인 연관성이 있지는 않지만 한편으로 한글이라는 글자를 세종대왕께서 과학적으로 창제하여 지금껏 잘 사용할 수 있는 것에 다시금 감사하게 생각할수 밖에 없다.
Amharic (Ethiopia) አማርኛ (ኢትዮጵያ)
Armenian (Armenia) Հայերեն (Հայաստան)
Assamese (India) অসমীয়া (ভাৰত)
Bengali (Bangladesh) বাংলা (বাংলাদেশ)
Bengali (India) বাংলা (ভারত)
Divehi (Maldives)‎ ދިވެހިބަސް (ދިވެހި ރާއްޖެ)‏
Georgian (Georgia) ქართული (საქართველო)
Gujarati (India) ગુજરાતી (ભારત)
Hindi (India) हिंदी (भारत)
Inuktitut (Syllabics) ᐃᓄᒃᑎᑐᑦ (ᖃᓂᐅᔮᖅᐸᐃᑦ)
Inuktitut (Syllabics, Canada) ᐃᓄᒃᑎᑐᑦ (ᑲᓇᑕᒥ)
Kannada (India) ಕನ್ನಡ (ಭಾರತ)
Kazakh (Kazakhstan) Қазақ (Қазақстан)
Khmer (Cambodia) ខ្មែរ (កម្ពុជា)
Konkani (India) कोंकणी (भारत)
Lao (Lao P.D.R.) ລາວ (ສ.ປ.ປ. ລາວ)
Malayalam (India) മലയാളം (ഭാരതം)
Maltese (Malta) Malti (Malta)
Maori (New Zealand) Reo Māori (Aotearoa)
Marathi (India) मराठी (भारत)
Mongolian (Traditional Mongolian) ᠮᠤᠨᠭᠭᠤᠯ ᠬᠡᠯᠡ
Mongolian (Traditional Mongolian, PRC) ᠮᠤᠨᠭᠭᠤᠯ ᠬᠡᠯᠡ (ᠪᠦᠭᠦᠳᠡ ᠨᠠᠢᠷᠠᠮᠳᠠᠬᠤ ᠳᠤᠮᠳᠠᠳᠤ ᠠᠷᠠᠳ ᠣᠯᠣᠰ)
Nepali (Nepal) नेपाली (नेपाल)
Oriya (India) ଓଡ଼ିଆ (ଭାରତ)
Pashto (Afghanistan)‎ پښتو (افغانستان)‏
Punjabi (India) ਪੰਜਾਬੀ (ਭਾਰਤ)
Sanskrit (India) संस्कृत (भारतम्)
Sinhala (Sri Lanka) සිංහ (ශ්‍රී ලංකා)
Syriac (Syria)‎ ܣܘܪܝܝܐ (سوريا)‏
Tamil (India) தமிழ் (இந்தியா)
Telugu (India) తెలుగు (భారత దేశం)
Tibetan (PRC) བོད་ཡིག (ཀྲུང་ཧྭ་མི་དམངས་སྤྱི་མཐུན་རྒྱལ་ཁབ།)
Yi (PRC) ꆈꌠꁱꂷ (ꍏꉸꏓꂱꇭꉼꇩ)


 두번째 항목인 압축 암호의 코드페이지 종류가 또다른 골칫거리가 된다. MS에서 제공하는 National Language Support (NLS) API Reference을 가 보면 각각의 언어와 관련된 로케일에서 사용되는 ANSI, OEM 코드페이지가 무엇인지 쉽게 잘 알 수 있다. 이것이 무슨 연관성이 있는가 하면, 압축을 할 때 암호 문자열에 대한 인코딩과 문자셋에 지정을 하는 규정이 AppNote에 없기 때문에 윈도우의 경우에는 OEM 코드페이지와 연관된 한쌍의 ANSI 코드페이지를 사용 한다. 결과적으로, 한글 윈도우에서 압축파일에 한글로 암호를 준 것을 다른 외국 윈도우 사용자에게 전달하면 그 사용자는 윈도우에서 사용되는 CP949코드페이지의 한글문자열을 똑같이 입력해야 압축해제를 할 수 있다는 사실이다.

 설상가상으로 위에서 소개한 링크에서 찾아보면 하나의 로케일에서 OEM코드페이지와 ANSI코드페이지가 다른 언어들이 있는데 이 경우에는 상황이 더 복잡해진다. 글 처음에서 소개했듯이 압축시 암호는 ANSI코드페이지를 사용한다고 했기에 가령 히브리어 윈도우에서 압축한 'עִבְרִית'란 파일과 압축암호가 실제 헥사코드로는 값이 각각 다르다는 의미이다. 이런 고려를 하지 않은 압축 프로그램들은 이런 압축 파일을 제대로 다룰 수 없게 된다.
 그래서 이런 사실을 사용자들이 제대로 인식하고 사용을 해 주었으면 한다. 그리고 가능하면 .zip 압축파일의 암호에는 알파벳 문자와 기본적 숫자,기호만을 사용하는게 보안상 취약성이 올라간다고 할지는 모르겠지만 다국어 사용자들간 .zip 파일 교환의 측면에서는 바람직해 보인다. 또한 앞으로 zip파일에 UTF-8을 사용한 압축을 하고 암호에도 UTF-8문자열을 사용한다면 반드시 정규화에 대한 고려를 해 주거나 사용자들의 인식이 되 있어야 하지 않을까 하는 바램이다. 보기에는 똑같지만 다른 글자인 암호를 사용해서 윈도우와 OSX사이의 파일 교환에 곤란한 일이 일어날 수도 있기 때문이다.

 마지막으로 가급적이면 유니코드 사용이 기본인 .7z, .rar 포멧을 사용하는것을 추천하지만, 관성의 법칙으로 인해서 사용자들에게 무조건 바꾸라고 하기에는 힘든것이 사실이다. 그런 이유에서라도 MS나 Apple등 기업에서 적어도 UTF-8파일명 사용 플래그를 제대로 인식하는 압축 프로그램을 기본으로 제공해 주었으면 하는 바램이다. 하지만 실제 그렇지 않은 현실에서 사용자들이 위와 같은 내용을  제대로 인식을 한 상태에서 사용을 하면 이런저런 애로사항을 줄일 수 있지 않을까 생각한다. 그리고 각각의 써드파티 압축 프로그램들이 정규화나 기본 다국어 평면을 벗어나는 유니코드 글자 지원이 아직까지는 미비한 경우가 많은데 이에 대한 지원을 힘써서 zip포멧에서 제대로된 유니코드 압축 지원을 해 주었으면 좋겠다.
Posted by trip2me
,
디스크 이미징 프로그램을 받아서 빌드하던 중 아래와 같은 에러가 났다.

ld_classic: can't locate file for: -lcrt0.o

즉 crt0.o를 찾지 못한다는 이야기인데 구글링해 보니 Apple Developer문서에 있는 내용이었다.

결론은 애플에서는 static링킹을 지원하지 않고 있으므로 가급적 dynamic linking을 사용하여 crt1.o를 링크하라는 내용이었다. 결국 그래서 Makefile에 있는 -static 옵션을 제거하고 동적으로 링킹해서 빌드를 했다.

그리고 반드시 static linking이 필요한 경우라면 Open Darwin에서 Csu 라는 모듈을 다운받아서 빌드후 crt0.o 를 사용하라고 한다. 단 이 모듈은 업데이트가 되지 않으므로 릴리즈 업데이트시 수동으로 빌드를 해 주어야 하는 단점이 있다.


다운받은 Csu module을 빌드할 때
export RC_ARCHS="ppc i386 ppc64 x86_64"
식으로 지정 후 make하면 원래 /usr/lib에 있던 기존 crt1.o와 같은 4가지 아키텍쳐를 지원하게 빌드 가능하다.

10.5.6에서 빌드한 Csu-75 결과물을 첨부파일로 올린다. tarball을 풀어서 crt0.o를 /usr/lib 에 집어넣고 빌드해 주거나 static 빌드하는 패키지에서 적당히 파일 링크를 추가하면 된다.
Posted by trip2me
,
Mac OS X에서 POSIX 규격의 세마포어는 사실 Mach semaphore 기반으로 구현이 되어 있다고한다 ( Mac OS X Internals 도서 9.18.5 참고 ).

한가지 사소한 문제점이라면 OS X에서 POSIX규격의 unnamed semaphore(binary semaphore)가 구현되어 있지 않다는 점이다. 그래서 POSIX unnamed semaphore를 구현하려면 2가지 대체 방안을 사용할 수 있다.
  1. POSIX의 named semaphore를 사용
  2. Mach semaphore를 사용

 POSIX의 named semaphore를 사용하는 방법은 POSIX unnamed semaphore를 생성할때 사용하는 함수인 sem_init()대신 sem_open()을 사용하는 방법이다. sem_open("/tmp/sem", O_CREAT, 0777, 0)) 처럼 구체적인 파일을 열어야 한다.

 두번째 방법인 Mach semaphore를 사용하는 방법은 애플 데벨로퍼 사이트를 참고하면 된다. 세마포어를 만들때 semaphore_create()를 사용하는데 조금 다르다. 사이트를 읽어보면 바로 깨어난 쓰레드가 다시 run되는 stavation을 피하도록 설계되었다고 하니 참고할 것.

Using counting semaphores on Mac OS X 링크의 글도 참고~
Posted by trip2me
,
서브버전으로 svn commit시 영어 이외의 언어를 사용하고 완료를 할 경우 아래와 같은 메시지가 출력되었디

svn: Commit failed (details follow):
svn: Can't convert string from native encoding to 'UTF-8':

사용자 삽입 이미지

이유는 간단하다.
.inputrc 파일을 수정해서 한글이 나온다 하더라도
실제 로케일 설정이 C 로 되어있었던 것이었다.
그럴 경우 서브 버전이 한글을 인코딩하지 못하고 저런 메시지를 출력하게 된다.
간단히 로케일 설정을 해 주면 submit할때 영어 이외의 문자를 사용가능하다.

export LANG=en_US.UTF-8을 하거나 export LC_CTYPE=en_US.UTF-8 만 설정하면 더이상 svn이 불만을 토로하지 않는다.

사용자 삽입 이미지
Posted by trip2me
,
대부분의 프로토콜이나 화일들은 자신만의 특정 헤더 부분이 있다.
어디서부터 어디까지는 무슨 데이터이고... 이런 것들.

그런 헤더의 내용을 편리하게 가져오기 위해서 C/C++에서는 struct라는 구조체를 사용하여 불러오는 경우가 많다. 그렇게 하면 나중에 클래스의 어트리뷰트처럼 '구조체.필드이름'으로 접근할 수 있으니까.

그런데 여기서 한번 생각해 보아야 할 것이 과연 저런 구조체를 컴파일러는 어떻게 내부적으로 구현을 해 놓을까? 란 것이다.

컴퓨터 구조나 운영체제 시간에 메모리의 alignment라는 것을 들어 본 적이 컴공관련 학우라면 있을것이다.

워드단위로 메모리 입출력을 수행하는 중앙처리장치가 빠르게 값을 가져 올 수 있도록 하기 위해서 중앙처리장치의 처리단위 워드크기 경계로 맞추어 값을 배치하게 하는 것이 바로 'word alignment'이다.

프로토콜 헤더 정의를 잘 해서 프로그램에서 읽어온 값이 정작 쓰레기로 나오는 이유가 바로 저녀석 때문이다.

가령 CPU의 기본 처리 워드 크기가 32비트 ( 32bit CPU이라면... ) 일 경우 4바이트가 한 워드가 된다.

이러한 상황에서 비트맵파일의 헤더부분인 아래의 구조체는

typedef unsigned short WORD;
typedef unsigned int DWORD;

typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 'BM'이라는 identifier를 가짐.
DWORD bfSize; // 바이트단위 전체 파일크기
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits; // 파일의 첫위치에서 영상데이터 까지의 거리
} BITMAPFILEHEADER;


에서 WORD는 2바이트이고 DWORD가 4바이트라고 할 경우 bfType가 2바이트이므로 워드 정렬을 위해서 2바이트가 더 삽입되어 빈공간이 추가된 후 bfSize가 위치하게 되므로

sizeof(BITMAPFILEHEADER) 를 하면 14를 예상하겠지만 실제 16이 나온다.
궁금하면 해보기 바란다. 물론 CPU의 기본 워드단위에 따라 어찌 다르게 나올지도 모른다.

결론적으로 위의 상황에서는 도저히 프로토콜 헤더를 구조체를 이용해서 읽어오는게 불가능해 진다.
이를 해결하기 위해 컴파일러에게 워드 정렬을 다르게 하라고 지시를 해야한다.

이를 하는 지시어가 #pragma pack() 이다.
C/C++의 Standard에는 들어가는 사항이 아니지만 대부분의 컴파일러에서 사용가능하다.
컴파일러마다 조금씩 다른 용법을 가지고 있겠지만, 기본적으로

#pragma pack() 은 원래의 컴파일러 기본 워드정렬로 돌아오는 지시어이고
#pragma pack(n) 을 사용하면 (n은 2의 거듭제곱수. 1,2,4,8...) 지정한 n바이트로 워드 정렬을 수행하게 된다.

위의 경우 #pragma pack(2)를 해야 중간에 빈 공간이 생기는 경우가 없어진다.

typedef unsigned short WORD;
typedef unsigned int DWORD;

#pragma pack(2)
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 'BM'이라는 identifier를 가짐.
DWORD bfSize; // 바이트단위 전체 파일크기
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits; // 파일의 첫위치에서 영상데이터 까지의 거리
} BITMAPFILEHEADER;
#pragma pack()


나중에 구조체를 만들어서 헤더파일등을 import 할 경우 반드시 고려 해야 한다.

기타 플랫폼별 컴파일러별 pack() 지시어의 특이사항에 관련된 내용은 잘 알지 못해 올리지 않았다. 각 벤더별 메뉴얼을 참조하기 바란다.

"Structure Packing"로 검색해보면 관련된 많은 내용이 나온다.
Posted by trip2me
,
벡터 연산이랑 복소수 연산이 필요해서 GNU의 (GSL - GNU Scientific Library)를 맥에 설치했다.

그리고 샘플을 컴파일하니 컴파일은 되고 링크에러가 아래처럼 났다.

~/trip2me$ gcc main.c
/usr/libexec/gcc/i686-apple-darwin8/4.0.1/ld: Undefined symbols:
_gsl_sf_bessel_J0
collect2: ld returned 1 exit status


검색을 통해서 DYLD_LIBRARY_PATH, LIBRARY_PATH, C_INCLUDE_PATH, CPLUS_INCLUDE_PATH 라는게 있다는 사실을 알고 환경변수에 /usr/local/bin을 추가해 주었지만 역시나 링킹이 되지 않았다. 왜!!! ㅠ_ㅠ;

결국 혹시나 해서
gcc -l gsl main.c
를 하니 아무말 없이 빌드 ㅡㅅㅡ;
그래 난 아직 완전 초보란 것이다.

PS. 그나저나 그럼 Xcode에는 저걸 어디다가 적어주지???
Posted by trip2me
,
이 재홍님의 사이트에 아주 잘 만들어진 튜토리얼이 있다.

내가 예전에 잘못 알고 있었던 사실이 svnserve를 이용해서 리파지토리를 운영할 경우
"svnserve -d -r /home/svn/프로젝트명"형식으로 프로젝트명을 넣고 데몬을 띄운 후
'svn co svn://trip2me.ce.knu.kr/project' 하니 리파지토리가 없다고 에러를 내는데 왜 그런가 했다.

에혀... 모르는게 죄다.
이제는 제대로 설정 할 수 있다. ㅋ
Posted by trip2me
,

Gabor filter

Programming_life 2007. 11. 6. 19:13
$G(x,y,\omega ,\sigma ,\gamma ,\theta ) = \frac{1}{{\sqrt {\pi \gamma \sigma } }}e^{ - \frac{1}{2}\left[ {\frac{{\left( {\gamma R_1 } \right)^2 + R_2^2 }}{{\left( {\gamma \sigma } \right)^2 }}} \right]} e^{i\omega R_1 }$ $R_1 = x \cdot \cos \theta + y \cdot \sin \theta ,R_2 = - x \cdot \sin \theta + y \cdot \cos \theta$
Posted by trip2me
,