Archive for the 'Computer' Category

정태영

컴퓨터 공학을 전공하다보면 실습을 해야할 일이 잦은데, 무료로 나와있는 편리한 개발툴이 많지 않다보니 불법 소프트웨어를 사용하는 일이 잦은 형편입니다. 아무래도 Visual Studio 등의 비싼 가격도 이런 현실에 한 몫해온 것이 사실이죠.

물론 Visual Studio Express Edition 이란 이름으로 MFC 등이 빠진 버젼을 학생들에게 무료 배포하곤 했지만, OpenGL 이라거나 MFC 등을 실습해야 하는 경우에는 이것으로 커버하기가 쉽지 않았던 것이 사실입니다.

하지만 대학생들에 한해서는 더 이상 불법 소프트웨어로 실습할 필요가 없어졌습니다.. Microsoft 에서 개발 툴들을 대학생들에 한해 무료 배포하기 시작했거든요.

http://www.microsoft.com/korea/msdn/dreamspark/index.aspx

위 URL 을 참고해보시면 알겠지만, Visual Studio 2005/2008 Professional Edition 에 국한되는 것이 아니라 Expression Studio 라거나 Windows Server 2008 Standard Edition, SQL Server 2008 Developer/Express Edition 까지 포함하고 있습니다. 용도에는 맞지는 않더라도 Windows Server 2008 를 사용하면 OS 마저 무료로 사용할 수 있겠습니다.

물론 우분투에서 gcc 와 eclipse, mysql 등을 사용하는 것도 좋은 선택일 수 있겠지만, 라이센스나 추가 비용을 걱정하지 않고 실습 할 수 있는 또 하나의 적법한 환경이 생겼다는 점은 상당히 고무적이네요.

정태영

국내 포털 중 하나인 다음 측에서 새로운 공개 서체를 발표했습니다. 자유롭게 사용할 수 있는 양질의 한글 서체가 하나 둘 늘어가는 현실에 기분이 참 좋습니다.

http://fontevent.daum.net/

서체 이름은 ‘다음’ 이고, 레귤러와 세미볼드 이렇게 두 가지 스타일로 제공되고 있지만, family name 이 각각 ‘Daum_Regular’ 와 ‘Daum_Semibod’ 로 서로 다르기 때문에 같은 서체로 인식이 되지는 않습니다. 각 서체의 적용 예는 아래에…

사실 family name 이 같아도 윈도우에서는 같은 서체의 다른 type 으로 분류되지는 않으므로 윈도우에서는 별 차이가 없겠지만, 같은 family 끼리는 묶어서 사용할 수 있는 맥과 리눅스 입장에서는 조금 아쉬운 측면이 아닐까 싶습니다.

어쨌든! 새로운 서체가 추가된 김에 font-sample 페이지도 업데이트 해보았습니다. :)

정태영

얼마 전부터 보이던 네이버에서 파이어폭스를 수정해서 배포할 계획이란 소식에 여러가지 루머들이 많았었는데, 다행히 걱정하던 방향으로의 수정이 아닌 것 같아 다행입니다. 원래는 Firefox 에 naver 익스텐션을 포함해서 배포할 계획이었으나, firefox 란 이름을 포함해서 배포를 하려면 모질라 재단과 협의가 되어야 한다는군요. 그 협의가 길어짐에 따라 우선 익스텐션만이 공개되었습니다.

http://t.lab.naver.com/firefox/

익스텐션의 역할은

  1. 네이버 테마
  2. 주소창에 검색어를 입력시 네이버를 통한 검색결과를 보여줌
  3. 네이버 서비스 바로가기 버튼 추가

이 정도인 것 같습니다. 들려오던 ‘activeX 를 지원하도록 만든다’ 같은 소식들은 루머로 밝혀졌네요. 설마 IE mode 를 기본으로 해서 배포하는게 아닐까 하는 걱정을 했었는데 말이죠. :)

이 익스텐션 개발과 관련된 뒷 얘기가 궁금하시다면 아래 링크도 한 번 방문해보세요.

http://kldp.org/node/97601

버그 리포트나 패치도 받는다고 하네요. 상품도 있다고 하니 관심있으신 분들은 한 번 도전해보시길…

http://kldp.org/node/97676

정태영

Internet Explorer 8 Beta2 에 포함된 개발툴이 소개되었는데, 이거 굉장히 멋지네요. 우선 8 Beta1 에서 소개된 개발툴의 장점들은 다음과 같습니다.

  1. 기본으로 포함되어 있으며 사용하기가 쉬움
  2. 비쥬얼 인터페이스를 제공
  3. 빠르게 실험이 가능

Beta2 에서는 이보다 훨씬 더 멋진 기능들이 추가되었는데, 이는 다음과 같습니다.

JScript 의 프로파일링과 디버깅

Beta2 에서는 just-in-time-debuging 을 위한 Console.log 를 지원합니다. 바로바로 에러메시지 등을 콘솔에 찍어볼 수 있기 때문에 굉장히 편리할 것 같네요.

하지만 디버거는 사이트가 그저 돌아가게 정도밖에는 도움을 주지 못합니다. 그렇기 때문에 사이트를 최적화하는데 도움을 주기 위해 Beta2 부터는 JScript 프로파일러를 제공하고 있습니다. 사용법도 매우 간단합니다. ‘Start Profiling’ 을 클릭한 뒤 사이트를 이용하다가 ‘Stop Profiling’ 을 클릭하는 것만으로 끝! 그동안 어떤 코드가 얼마나 많은 시간을 잡아먹었는지는 아래 스크린샷에서와 같이 표현됩니다.

이에 대한 더 자세한 내용은 스크립트 디버깅하기스크립트 프로파일링하기 를 참고하시면 되겠습니다.

HTML 과 CSS 다루기

Beta1 에서는 HTML 의 라이브(실시간) 에디팅만을 지원했지만 Beta2 에서는 HTML 과 CSS 모두 라이브 에디팅을 사용할 수 있습니다. CSS 의 경우 속성(Property) 이름, 값, 셀렉터 타입 등을 클릭해서 값을 바꿔줄 수 있습니다.

HTML 의 순서를 바꿔준다거나 엘리먼트 일부를 추가/제거 하기 위해 HTML 자체를 수정하는 것도 가능합니다. ‘HTML Editable’ 버튼을 클릭함을써 트리뷰 형태와 HTML 에디터 모드를 자유롭게 옮겨다닐 수 있네요.

페이지가 새로고침 되거나 다른 페이지로 넘어갈 경우 수정한 내용은 사라져 버리게 됩니다. 그렇기 때문에 수정된 HTML 과 CSS 를 파일로 저장할 수 있는 기능이 포함되었으며, windiff 를 사용했을 때와 같이 원본 파일과 달라진 부분만을 저장하는 것도 가능합니다.

호환성 테스트

호환성 테스트를 쉽게 하기 위해 개발 툴에서는 ‘Browser mode’ 와 ‘Document mode’ 메뉴를 제공합니다. ‘Browser mode’ 를 통해 다른 버젼의 익스플로러를 흉내낼 수 있으며, ‘Document Mode’ 를 통해서는 doctype 이나 meta tag 를 통해 지정된 렌더링 모드를 바꿔볼 수 있게 됩니다.

간단한 사용법

Beta2 에서는 사용자 친화적인 툴을 만들기 위해 굉장히 노력을 많이 했다네요. 그렇기 때문에 따로 뭘 설치할 필요나 개발툴을 사용하기 위해 ‘고급(Advanced)’ 탭을 클릭하는 노력을 제거해버렸습니다. 최소한의 클릭으로 툴을 사용할 수 있도록 만들었다는군요.

개발자들은 키보드를 사랑하는 경향이 있기 때문에 자주 사용하는 기능들에는 단축키가 배정되었습니다. 예를 들어 F12 는 툴을 여는 역할을 하고, CTRL+E 는 검색 상자에 포커스를 만드는 역할을 하게 됩니다. F3 과 Shift+F3 은 다음 검색 결과로 넘어가는 역할이네요. 단축키에 대해 더 알아보고 싶으시다면 ‘전체 단축키’ 문서를 참고하시기 바랍니다.

거기다가 툴바가 더 이뻐졌고, 자주 사용하는 기능들은 더 빠르게 접근할 수 있도록 개선이 있었다고 합니다. 더 쉽게 문법을 확인할 수 있도록 구문 강조(Syntax Highlighting) 기능이 추가되었구요.

또 툴바 형태로 개발툴을 익스플로러 내부에 붙여놓을 수도 있고, CTRL+M 이나 최소화 버튼을 이용 메뉴에만 표시되도록 만드는 것도 가능해졌다네요.

아직 베타 단계이므로 실제 사용에 있어서는 문제가 있을 지도 모르겠지만, 제공하려는 기능들만 봐서는 굉장히 인상적입니다. 이 글 대부분은 IEBlog 에 영문으로 기재된 내용을 대충 한글로 옮긴 것이므로 오역이나 잘못 이해한 부분이 있을 수도 있습니다. 원문이 궁금하신 분은 아래 링크를 따라가보시면 되겠습니다. :)

http://blogs.msdn.com/ie/archive/20…-in-internet-explorer-8-beta-2.aspx

그럼 다들 즐거운 하루 보내세요.

정태영

요번 학기에도 웍스테이션 실을 제가 관리하게 되었고, 2학기에는 리눅스 실습 수업이 있는 관계로 지난 일요일에 34대의 PC 에 우분투를 설치했습니다. 우분투 8.04 가 릴리즈될 때 32bit 용 우분투를 18장 신청했는데, 요번엔 군말없이 다 보내준 관계로 시디를 굽는 노가다를 안해도 됐네요. 휴~

우선 우분투 8.04 인스톨러는 7.10 의 인스톨러에 비해 훨씬 좋아진 느낌입니다. 처음에 어떤 언어로 설치를 진행할 지 선택할 수 있기 때문에 한글로도 인스톨을 진행할 수 있습니다. ‘다음’ 버튼만 클릭하다보니 설치가 끝나버리네요. 클릭 6번만으로 깔끔하게 설치 종료!

대부분의 하드웨어를 알아서 잡아주었지만, 보드에 내장된 nvidia 의 geforce6100 의 경우엔 약간의 문제가 있었습니다. 그나마도 ‘시스템/하드웨어 드라이버’ 메뉴를 통해 nvidia 의 바이너리 드라이버를 설치하기만 하면 되네요. 메인보드 시디를 넣고 드라이버를 설치하거나 인터넷에서 드라이버를 받아 설치해야하는 윈도우와 아주 대조적입니다. 조금 더 있으면 설치가 너무 어려워서 윈도우는 못쓰겠다는 말도 나올 거 같아요. 아쉬운 점은 nateon 이 아직도 메인 패키지 트리에 포함되지 않았다는 점 정도?

그런데 아무 말썽 없이 세팅이 끝날 리가 없지요! yellow page 를 설정하다 약간의 문제가 만났습니다. nfs 는 nfs-common 를 설치하는 것으로 간단히 끝났는데, nis 가 말썽! 초기 부팅시에 ypbind 가 실패하는 증상이 발견되었습니다. 아예 안되면 설정을 잘못했다고 생각할텐데, 신기하게도 nis 서비스를 재시작해줄 경우 아주 잘 동작한다는거죠. 타이밍 문제인가 싶어서 nis 서비스를 조금 더 늦게 시작하도록 고쳐봤지만 문제는 해결되지 않았습니다. 비굴하게 rc.local 에서 nis 서비스를 재시작하도록 해두는 것으로 문제는 해결됐지만 야매로 해결한 것이다보니 만족스럽지가 않네요.

2001년 처음 알짜 리눅스를 만나고, 레드햇, 한컴 등등을 거쳐 젠투에 안착해있다가 요근래 우분투도 여기저기 많이 적용해보고 있는데, 다들 각기 장단점이 있는 것 같습니다. 오라클같은 비오픈소스 상용 소프트웨어를 사용하려면 레드햇 혹은 CentOS 등이 좋은 선택일테고, 별 생각없이 간단한 데스크탑으로 사용하려면 우분투가 좋은 선택이 될 수 있을 거라 생각합니다. 물론 개인적인 패치들이라거나 실험적인 기능들(spf/srs 등과 같은)을 적극적으로 활용해보려면 젠투도 좋은 선택일테구요.

하여튼 gtk-2.0 이 발표되던 시점 이후로 리눅스 데스크탑은 정말 굉장한 속도로 발전하고 있네요. gnome-2.0 때만 해도 웹브라우져에선 동영상 하나 제대로 볼 수 없었고, (mplayer plug-in 은 그 당시 존재하지 않았습니다. vlc 의 모질라 플러그인도 마찬가지) 플래쉬 플러그인은 심심하면 브라우져를 폭발시켰었는데 말이죠. 정말 이런 속도로 발전해간다면 앞으로의 리눅스 데스크탑은 얼마나 더 멋져질지 너무나 기대되네요.

p.s) 오랫만에 다시 보는 제 예전 리눅스 데스크탑 스크린샷들~

http://mytears.org/resources/etc/screenshot/linux/

정태영

kldp 를 눈팅하다가 오늘 재밌는 문서를 읽게 되었습니다. 2001년도에 AMD 에서 나온 문서였는데, 그 내용이 상당히 흥미로워서 몇 가지 내용을 옮겨볼까 합니다.

메모리에서 연속된 값들을 다른 곳으로 복사하기 위해 사용할 수 있는 가장 간단한 어셈블리 코드는 다음과 같습니다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) shl ecx, 3 // convert to byte count rep movsb

rep movsb 명령은 repeat move single byte (바이트 단위로 값들을 반복해서 옮긴다.)라는 의미를 가집니다. esi 가 가리키는 곳에 있는 값을 edi 로 ecx 에 있는 개수 만큼 복사하게 됩니다. 이렇게 할 경우 일초에 약 620MB 를 복사할 수 있다고 하네요.

이 코드를 byte 단위가 아니라 4 byte 단위로 반복해서 복사를 하도록 하면 어떻게 될까요? 우선 코드는 다음과 같이 변하겠네요.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) shl ecx, 1 // convert to DWORD count rep movsd

shl 인스트럭션은 두개의 오퍼랜드를 가지며 (shl operand1 operand2) operand1 에 있는 값을 operand2 에 있는 값만큼 왼쪽으로 shift 를 시키게 됩니다. movsd 는 mov single dword[1] 라고 보시면 됩니다.

결과적으로 이렇게 코드를 수정함으로 인해 1초에 640MB 를 복사할 수 있게 됩니다. 3% 정도 성능 향상이 생기네요.

그런데 최근에 나온 프로세서들에서는 rep 같은 복잡한 인스트럭션을 내부적으로 RISC 명령으로 바꿔서 실행하다 보니, 그리 효율적이지 못하답니다. 그러므로 rep 를 사용하지 말고 반복문을 사용해보도록 합시다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) shl ecx, 1 // convert to DWORD count copyloop: mov eax, dword ptr [esi] mov dword ptr [edi], eax add esi, 4 add edi, 4 dec ecx jnz copyloop

코드가 뭔가 좀 길어졌죠? 위 코드를 c로 표현하면 아래와 같습니다.

int* src = esi; int* dst = edi; int i; for( i = len ; i != 0 ; i-- ){ dst++ = src++;

c로 표현하니 어디서 많이 쓰던 코드죠? 쨌든! 이렇게 하니 1초에 650MB 를 복사할수 있었고 결과적으로 1.5% 정도 성능이 향상되었답니다.

그럼 여기다가 Loop 코드를 최적화 하는 기법인 Loop Unrolling 을 적용해봅시다. [2]

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) shr ecx, 1 // convert to 16-byte size count // (assumes len / 16 is an integer) copyloop: mov eax, dword ptr [esi] mov dword ptr [edi], eax mov ebx, dword ptr [esi+4] mov dword ptr [edi+4], ebx mov eax, dword ptr [esi+8] mov dword ptr [edi+8], eax mov ebx, dword ptr [esi+12] mov dword ptr [edi+12], ebx add esi, 16 add edi, 16 dec ecx jnz copyloop

자 룹을 펼쳤더니 1초에 640MB 를 복사하였고, 결과적으로 1.5% 만큼 성능이 떨어졌습니다. 하지만 다행히도 Loop Unrolling 을 적용하고 나니 최적화를 할 여지가 많아졌네요.

캐쉬를 좀 더 잘 활용할 수 있도록 코드 순서를 바꿔봅시다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) shr ecx, 1 // convert to 16-byte size count copyloop: mov eax, dword ptr [esi] mov ebx, dword ptr [esi+4] mov dword ptr [edi], eax mov dword ptr [edi+4], ebx mov eax, dword ptr [esi+8] mov ebx, dword ptr [esi+12] mov dword ptr [edi+8], eax mov dword ptr [edi+12], ebx add esi, 16 add edi, 16 dec ecx jnz copyloop

이젠 1초에 660MB 를 복사할 수 있게 되었고, 3% 만큼 성능 향상이 일어났습니다.

여기서 끝이 아닙니다. 첨에 movsb 대신 movd 를 사용해서 1byte씩이 아닌 4byte 씩 복사를 하는 방법을 통해 최적화를 진행했었는데요, MMX 를 사용할 경우 movq 등의 인스트럭션을 이용해서 한 번에 8byte 씩을 복사하는게 가능해집니다. 또한 mm0~7 이라는 특수한 레지스터를 활용할 수 있으니 8*8 = 64 즉 한번에 64byte 씩을 복사해봅시다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) lea esi, [esi+ecx*8] // end of source lea edi, [edi+ecx*8] // end of destination neg ecx // use a negative offset copyloop: movq mm0, qword ptr [esi+ecx*8] movq mm1, qword ptr [esi+ecx*8+8] movq mm2, qword ptr [esi+ecx*8+16] movq mm3, qword ptr [esi+ecx*8+24] movq mm4, qword ptr [esi+ecx*8+32] movq mm5, qword ptr [esi+ecx*8+40] movq mm6, qword ptr [esi+ecx*8+48] movq mm7, qword ptr [esi+ecx*8+56] movq qword ptr [edi+ecx*8], mm0 movq qword ptr [edi+ecx*8+8], mm1 movq qword ptr [edi+ecx*8+16], mm2 movq qword ptr [edi+ecx*8+24], mm3 movq qword ptr [edi+ecx*8+32], mm4 movq qword ptr [edi+ecx*8+40], mm5 movq qword ptr [edi+ecx*8+48], mm6 movq qword ptr [edi+ecx*8+56], mm7 add ecx, 8 jnz copyloop emms // empty the MMX state

MMX 용 레지스터들인 mm0~7 은 FPU stack 의 일부를 활용하게 되므로, 이 레지스터 값을 바꿔주게 될 경우 FPU 와 관련해서 문제를 일으킬 수 있습니다. EMMX 는 이를 방지하기 위해 사용해야 하는 인스트럭션이 되겠습니다. 하여튼 이렇게 바꾸니 1초에 705MB 를 복사할 수 있게 되었고, 7% 만큼 성능이 향상되었습니다.

이젠 movntq 라는 인스트럭션을 통해 cache 를 우회해서 writing 을 진행해봅시다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) lea esi, [esi+ecx*8] lea edi, [edi+ecx*8] neg ecx copyloop: movq mm0, qword ptr [esi+ecx*8] movq mm1, qword ptr [esi+ecx*8+8] movq mm2, qword ptr [esi+ecx*8+16] movq mm3, qword ptr [esi+ecx*8+24] movq mm4, qword ptr [esi+ecx*8+32] movq mm5, qword ptr [esi+ecx*8+40] movq mm6, qword ptr [esi+ecx*8+48] movq mm7, qword ptr [esi+ecx*8+56] movntq qword ptr [edi+ecx*8], mm0 movntq qword ptr [edi+ecx*8+8], mm1 movntq qword ptr [edi+ecx*8+16], mm2 movntq qword ptr [edi+ecx*8+24], mm3 movntq qword ptr [edi+ecx*8+32], mm4 movntq qword ptr [edi+ecx*8+40], mm5 movntq qword ptr [edi+ecx*8+48], mm6 movntq qword ptr [edi+ecx*8+56], mm7 add ecx, 8 jnz copyloop sfence emms

movntq 를 활용한 다음에는 write buffer 를 비워주기 위해 sfence 를 사용해야 한다는군요. write 부분이 movq 에서 movntq 로 바뀌었고 emms 앞에 sfence 가 들어간 것을 제외하면 코드는 동일합니다. 하지만 성능 향상은 60% 로 굉장하네요. 1초에 1130MB 를 복사할 수 있었다고 합니다.

이젠 prefetch 도 활용해봅시다.

mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // number of QWORDS (8 bytes) lea esi, [esi+ecx*8] lea edi, [edi+ecx*8] neg ecx copyloop: prefetchnta [esi+ecx*8 + 512] // fetch ahead by 512 bytes movq mm0, qword ptr [esi+ecx*8] movq mm1, qword ptr [esi+ecx*8+8] movq mm2, qword ptr [esi+ecx*8+16] movq mm3, qword ptr [esi+ecx*8+24] movq mm4, qword ptr [esi+ecx*8+32] movq mm5, qword ptr [esi+ecx*8+40] movq mm6, qword ptr [esi+ecx*8+48] movq mm7, qword ptr [esi+ecx*8+56] movntq qword ptr [edi+ecx*8], mm0 movntq qword ptr [edi+ecx*8+8], mm1 movntq qword ptr [edi+ecx*8+16], mm2 movntq qword ptr [edi+ecx*8+24], mm3 movntq qword ptr [edi+ecx*8+32], mm4 movntq qword ptr [edi+ecx*8+40], mm5 movntq qword ptr [edi+ecx*8+48], mm6 movntq qword ptr [edi+ecx*8+56], mm7 add ecx, 8 jnz copyloop sfence emms

위 코드에는 현재 복사할 차례의 512 바이트를 미리 읽어두라는 의미의 prefetchnta 인스트럭션이 추가되었습니다. 한 번에 복사하는건 64Byte 인데 왜 512Byte 를 읽으라고 했는지 살짝 의문이네요. 제 생각에는 문서를 작성하신 분이 버그를 낸거라고 생각합니다.

하여튼 이젠 1초에 1240MB 를 복사할 수 있게 되었고, 10% 만큼 더 성능 향상이 생겼네요.

지금까지의 방법만으로도 꽤 많은 성능 향상이 있었지만, 한 번에 한 캐쉬 라인[3]만을 활용하고 있습니다. 하지만 실제 CPU 에는 훨씬 많은 캐쉬 라인이 존재하므로 이를 더 잘 활용할 수 있도록 코드를 수정해보겠습니다.

#define CACHEBLOCK 400h // number of QWORDs in a chunk mov esi, [src] // source array mov edi, [dst] // destination array mov ecx, [len] // total number of QWORDS (8 bytes) // (assumes len / CACHEBLOCK = integer) lea esi, [esi+ecx*8] lea edi, [edi+ecx*8] neg ecx mainloop: mov eax, CACHEBLOCK / 16 // note: prefetch loop is unrolled 2X add ecx, CACHEBLOCK // move up to end of block prefetchloop: mov ebx, [esi+ecx*8-64] // read one address in this cache line… mov ebx, [esi+ecx*8-128] // … and one in the previous line sub ecx, 16 // 16 QWORDS = 2 64-byte cache lines dec eax jnz prefetchloop mov eax, CACHEBLOCK / 8 writeloop: movq mm0, qword ptr [esi+ecx*8] movq mm1, qword ptr [esi+ecx*8+8] movq mm2, qword ptr [esi+ecx*8+16] movq mm3, qword ptr [esi+ecx*8+24] movq mm4, qword ptr [esi+ecx*8+32] movq mm5, qword ptr [esi+ecx*8+40] movq mm6, qword ptr [esi+ecx*8+48] movq mm7, qword ptr [esi+ecx*8+56] movntq qword ptr [edi+ecx*8], mm0 movntq qword ptr [edi+ecx*8+8], mm1 movntq qword ptr [edi+ecx*8+16], mm2 movntq qword ptr [edi+ecx*8+24], mm3 movntq qword ptr [edi+ecx*8+32], mm4 movntq qword ptr [edi+ecx*8+40], mm5 movntq qword ptr [edi+ecx*8+48], mm6 movntq qword ptr [edi+ecx*8+56], mm7 add ecx, 8 dec eax jnz writeloop or ecx, ecx // if( ecx != 0 ) jnz mainloop // goto mainloop sfence

여기서는 cache 가 1024 개의 cache line 을 가지고 있다고 가정했네요. (16진수인 400h 는 10진수로 바꿀 경어 1024 가 됩니다.) 미리 캐쉬 사이즈만큼 prefetch 명령들을 내려놓은 뒤 값들을 복사하게 될 때 쯤이면 이미 값들이 캐쉬에 올라와있게 되니 딜레이를 줄일 수 있게 되겠습니다.

효과가 있을까 싶지만, 실제 1초에 1976MB 를 복사할 수 있었고, 59% 의 성능향상이 추가로 발생했습니다. 초기 코드에 비하면 300% 의 성능 향상이라네요. 신기하죠. ;)

전 상당히 흥미롭게 읽었었는데, (비슷한 걸 해본 경험도 있고 해서) 재밌었는지 모르겠네요. sfence 나 movqnta, prefetchnta 같은 캐쉬와 관련된 명령들은 정확히 무슨 용도인지 이해하지 못하고 있었는데 이 문서를 통해 이해할 수 있었던 것 같네요. 관심이 있으신 분은 아래 문서를 읽어보시면 되겠습니다. FPU 관련된 최적화도 다루고 있는데, 관심이 없어서 그 부분은 옮기질 않았습니다. 그럼 다들 즐거운 주말 보내시길 ;)

http://kldp.org/files/AMD_block_prefetch_paper.pdf

[1] x86 호환 아키텍쳐에서는 사이즈를 byte, word, dword, qword, dqword 식으로 표현합니다. 이는 각각 1, 2, 4, 8, 16 바이트를 의미하며, word 가 2바이트이고 나머지의 앞에 붙은 알파벳들은 각각 double(*2), quad(*4), double quad(*8)를 나타내는 것이죠.

[2] Loop Unrolling 은 Loop 을 펼쳐서 파이프라인의 덕을 더 많이 볼 수 있도록 코드를 수정하는 방법입니다. 예를 들어

for ( i = 0 ; i < 16 ; i++ ) dst[i] = src[i];

위와 같은 코드를

for ( i = 0 ; i < 16 ; i+=4 ){ dst[i] = src[i]; dst[i+1] = src[i+1]; dst[i+2] = src[i+2]; dst[i+3] = src[i+3]; }

이렇게 바꿀 경우 branch 로 인한 pipeline hazard 도 줄일 수 있고, add instruction 도 1/4 만큼만 사용하게 됨으로 인해 성능이 향상될 여지가 많습니다.

[3] 메모리에 어떤 값을 읽어들일 때 CPU 에서는 바이트 단위로 값을 읽지 않고, block 단위로 값들을 cache 에 복사하는데, 이 block 의 크기를 cache line 이라고 표현합니다. 펜티엄 계열의 경우 대부분 64byte 입니다.

정태영

어쩌다가 몇 년전에 kldpcdk 의 포럼에서 제가 참여했던 쓰레드들을 다시 보게 되었습니다. 유니코드나 서체와 관련된 글들에서 가끔 흥분을 했던 기억이 있는데, 지금 다시 보니까 얼굴이 화끈화끈 거리는군요. 하여튼 ‘왜 공개 글꼴이 필요한가?’ 쓰레드를 보고 생각난 게 있어서 오랫만에 포스팅을 해보려 합니다.

현재 은글꼴, ttf-alee, 서울체, 남산체, 백묵 글꼴 등등 공개 글꼴들이 하나 둘 나타나기 시작하고 있지만, 아직도 화면용(On screen display)으로 특화된 서체는 없습니다. 그 때문에 웹에서는 IR(Image Replacement) 등의 방법을 통해 이미 렌더링된 이미지로 텍스트를 대체시키는 방법을 많이 사용하고 있는데, 왜 화면용 글꼴에는 다들 관심을 가지지 않는 것일지 조금 아쉽네요.

Microsoft 의 경우 화면 용으로 Webdings, Verdana, Georgia, Trebuchet MS, Comic Sans MS, Impact, Arial, Courier New, Times New Roman 등의 서체를 공개하고 있습니다. 다음 페이지를 참고해보시면 알겠지만 이 서체들은 대부분 IE 나 Microsoft Windows 에 기본으로 번들되어 있기 때문에 대부분 기본으로 설치되게 됩니다.

http://www.microsoft.com/typography/web/fonts/fonts02.htm

또한 다음 URL 을 참고해보시면 웹을 통해 다운로드 받은 뒤 매킨토시에서도 사용할 수 있다고 되어 있습니다. (Verdana, Trebuchet MS 등은 화면용으로는 불필요한 기능들을 제외시킨 화면용 글꼴입니다.) 게다가 Linux 에서도 흔히 Corefonts 란 이름으로 패키징되어 사용되고 있죠.

http://www.microsoft.com/typography/web/fonts/verdana/default.htm

물론 아무 제약 없이 사용할 수 있는 서체의 개발을 의뢰하는 데는 많은 비용이 드는 것으로 알고 있습니다. 그렇기 때문에 서울 남산체, 한강체 처럼 (서울시에서 주도했으니) 나라에서 주도해서 자유롭게 사용가능한 화면용 서체들이 좀 개발되었으면 하는 바램이 있네요. 뭐 조금 앞어나간다면 IE 서비스팩 등에 그 새로운 화면용 글꼴들이 포함되었으면 더 좋겠구요. (이런 건 정치적인 문제다보니…)