Memory ordering

ARM Cortex-A Series Programmer’s Guide의 11. Memory Ordering 장을 한글로 옮깁니다.

종래의 ARM 아키텍처에서 프로그램 명령은 순서대로 실행되었다. 즉, 이전 명령어의 실행이 완료된 후에 다음 명령어가 실행되었다. 최신 마이크로프로세서에서는 메모리 접근과 관련된 여러가지 최적화가 적용되었다. 프로세서의 명령어 실행 속도는 외부 메모리 속도에 비교할 수 없을 정도로 빠르다. 캐시와 버퍼는 이러한 속도 차이에서 발생되는 지연을 부분적으로 경감하기 위해 사용된다. 이는 잠재적으로 메모리 접근 순서의 불일치를 야기한다. 프로세서에서 실행된 load, store 명령어의 실행 순서는 외부 디바이스에서 이루어지는 실제 접근순서와 다를 수 있다는 것이다.

str r12, [r1]       @접근1 |-> 쓰기버퍼로 감
ldr r0, [sp], #4    @접근2 |-> 캐시미스
ldr r2, [r3, #8]    @접근3 |-> 캐시히트
                          |-> 접근3의 데이터를 레지스터로 리턴
                          |-> 접근2의 데이터가 리턴되고 캐시라인이 채워짐
                          |-> 접근1이 수행되고 메모리 쓰기가 trigger 됨
                          |
                          v

위 예제에서 첫번째 명령어는 외부 메모리에 쓰기를 수행하고 이는 캐시미스로 이어진다(접근1). 그리고 두번째 명령은 읽기를 수행하고 다시 캐시미스로 이어진다(접근2). 마지막 명령도 읽기를 수행하고 캐시히트가 된 결과 바로 데이터를 레지스터로 로드하게 된다(접근3). 두번의 읽기 연산은 모두 접근1의 쓰기버퍼write buffer의 쓰기가 완료되기 이전에 완료될 수 있다. 캐시의 hit-under-miss는 접근3처럼 캐시히트가 된 load 연산이 접근2처럼 이전에 실행되었지만 캐시미스된 load 연산보다 먼저 완료될 수 있다는 것을 말한다.

프로그래머가 작성한 코드 순서 그대로 하드웨어에서 실행될 것이라는 환상은 여전히 유효할 수 있다. 프로그래머가 직접 위와 같은 실행 순서의 불일치를 고려해야 할 경우는 많지 않기 때문이다. 일례로 CP15 레지스터를 수정하거나 메모리의 코드를 복사/변경하는 경우에 프로그래머는 관련 연산이 완료되기까지 기다려야한다(다음 연산이 수행되어서는 안된다).

성능을 개선하기 위해 speculative data accesses, multi-issuing of instructions, cache coherency protocols 그리고 out-of-order execution과 같은 기능을 지원하는 고사양 프로세서에서 재배치 가능성은 훨씬 높아진다. 하드웨어단에서 재배치로 파생할 수 있는 잠재적인 문제들을 해결해주기 때문에(데이터 의존성을 고려하고 리턴값의 무결성을 보장하는 등의) 일반적으로 싱글 코어 프로세서에서 프로그래머가 재배치 문제로 걱정해야 할 일은 잘 없다.

하지만 멀티프로세서에서 공유 메모리 접근은 재배치 문제를 더욱 악화시킨다. 보통 multiple execution threads가 동기화되어야 할 때마다 정확한 메모리 접근 순서를 유지해야 할 것이다.

ARMv7-A 아키텍처와 같은 프로세서는 weakly-ordered memory model을 따른다. 이는 load, store 연산이 프로그램 순서와 동일하다고 기대할 수 없다는 말이다. 이 모델은 LDR, LDM, LDD와 같은 읽기 연산을 이전의 읽기연산의 상호관계와 쓰기 연산 그리고 다른 특정 명령들과의 상호관계를 고려하여 재배치할 수 있다. Normal 메모리의 읽기/쓰기는 하드웨어에 의해 재배치될 수 있지만, 데이터 의존성이나 메모리 배리어 명령어로 재배치를 방지할 수도 있다. 명확한 메모리 접근 순서를 보장하기 위해서는 페이지 테이블 엔트리의 메모리 타입 속성을 설정하므로써 해당 영역의 메모리 접근 정책을 프로세서에게 알려야 한다. 하지만 메모리 접근 순서를 강제하는 것은 하드웨어 최적화를 제약하므로 성능과 전력사용에 부정적인 영향을 미친다. 따라서 프로그래머는 이와 같은 재배치 전략을 언제 어떻게 제약할 것인지 알아야 한다.

11.1 ARM memory ordering model

이미 살펴보았듯이 Cortex-A 시리즈의 프로세서는 weakly ordered memory model을 따른다. 하지만 특정 메모리 영역들은 Strongly-ordered로 설정될 수 있고, 이 영역으로의 메모리 접근은 이슈된 순서 그대로 일어날 것을 보장한다.

세개의 상호배타적인 메모리 타입이 정의되어 있다. 모든 메모리 영역은 이들 중 하나의 타입으로 설정된다:

Normal과 Device 메모리는 추가적으로 공유Shareable 또는 미공유로 지정할 수 있다. Normal 메모리는 inner/outer cacheable 속성을 지정할 수 있다.