지난 번의 간단한 memcpy는 유용성이 제한됨을 이미 말한바 있다. 이것을 좀더 유용하게 만드는 방안으로 고려할만한 것이 메모리 주소 정렬이다.

인텔계통의 32비트 CPU는 메모리를 4바이트 단위로 접근한다. (4바이트 단위라는 표현 대신 DWORD단위라는 표현이 더 익숙할 수도 있다.) 예컨대, 0x1234번지에서 4바이트를 읽을 때에는 0x1234번지부터 0x1237번지까지 한번 접근해서 4바이트를 읽어들인다. 한편, 0x1235번지에서 4바이트를 읽을 때에는 0x1235번지부터 0x1237번지까지 접근해서 3바이트를 읽고, 0x1238번지에 접근해서 1바이트를 읽는다. 같은 양의 데이타를 읽을 때, 메모리 접근 횟수가 많아지면 속도가 느려지는 것은 자명하다. 메모리로 자료를 쓸때에도 마찬가지 현상이 일어난다.

따라서, 자료를 읽어들이는 주소와 쓰는 주소를 4바이트 단위로 정렬하면, memcpy의 속도가 개선될 여지가 있다. 그런데, 두개의 주소가 동시에 정렬되지 않는 경우가 종종 발생한다. 예컨대,

memcpy(p, p+1, 10);
이와 같은 경우에는, 읽는 주소와 쓰는 주소가 동시에 4바이트 경계에 정렬될 수 없다. 이러한 경우에 어느 주소를 정렬할 것인가는 순전히 CPU에 의존한다.

과거에는 쓰는 주소를 정렬하는 것을 당연한 최적화로 받아들였다. 특히, WC메모리를 활용할 수 없는 오래된 CPU의 경우에는, 메모리로부터 읽을 때보다 메모리로 쓸 때에 주소를 정렬하는 것이 속도증진에 도움이 되었다. 하지만, 요즘의 CPU들의 경우에는 반드시 그렇지만은 않다. 그러므로, 어떤 주소를 정렬하는지가 더 나은가 하는 것은 자기가 사용하는 CPU에서 속도를 측정해봐야 결론을 내릴 수 있다.

쓰는 주소를 정렬하는 고전적인 경우를 가정하고 memcpy를 구현해보면 다음과 같다.

; 주소정렬을 고려한 memcpy
; void *memcpy(void *dst, void *src, size_t n)
memcpy  PROC C
        push    edi
        mov     edi,[esp+4+4]   ; dst
        mov     eax,edi         ; return value
        push    esi
        mov     esi,[esp+8+8]   ; src
        mov     edx,[esp+8+12]  ; n
        ; dst 주소 정렬.
        ; src를 정렬하려면 esi를 쓰면 된다.
        ; 본문 참조.
        mov     ecx,edi
        neg     ecx
        and     ecx,3
        sub     edx,ecx         ; 아주 짧으면?
        jbe     L0              ; 그러면 그냥 rep movsb
    rep movsb
        mov     ecx,edx
        and     edx,3
        shr     ecx,2
        ; 정렬된 주소로 복사.
    rep movsd
L0:     add     ecx,edx
    rep movsb
        pop     esi
        pop     edi
        ret
memcpy  ENDP

지난번의 코드와 달라진 부분은 빨간 글자로 표시된 부분이다. 새로 추가된 부분은 주소를 정렬하기 위해 미리 복사하는 부분이고, 두번째의 바뀐 부분은 rep movsd의 실행결과로 ecx의 값이 0이 되는 것을 고려하면 지난번의 mov ecx,edx와 동일한 역할을 하는 것을 쉽게 알 수 있다.

주소를 정렬하기 위해 미리 복사해야 하는 양은 정의상 현재 주소의 4의 보수의 마지막 자리이다. 2의 보수를 구하는 것과 같은 방법으로 NOT연산후에 1 증가시키는 방법으로 구할 수 있으며, 2의 보수로 음수를 표현하는 인텔 CPU에서는 편리하게 neg명령 써서 한번에 해결할 수 있다.

memcpy 구현 연재 목록
[1] 가장 단순한 구현
[2] 주소 정렬
[3] MMX 이용
[4] SSE로 확장
[5] 그외의 고려사항들
[6] 초보가 빠지기 쉬운 함정
Posted by movsd
,