奇安度
86년 한양대 전자공학과 학사
88년 KAIST 전기 및 전자공학과 석사
94년 한국전자통신연구원 선임연구원
97년 영국 맨체스터대학 컴퓨터사이언스 박사
97년∼현재 한국전자통신연구원 프로세서연구실 연구원
컴퓨터 기술의 발전으로 다양한 종류의 성능향상 기법들이 개발, 사용되고 있다. 하지만 이들 기법은 소프트웨어적인 이해와 처리가 뒷받침돼야 충분히 사용할 수 있다. 대표적인 것이 메모리모델이다. 이것은 하드웨어와 소프트웨어 사이의 약속으로 프로그램이 바라보는 하드웨어의 동작을 정확히 규정하는 것이다. 즉 프로그램이 발생시키는 읽기와 쓰기가 하드웨어적으로 어떠한 순서로 처리될 것인지 정확히 예측할 수 있도록 하는 것이다. 때문에 프로그램 작성자가 생각하는 알고리듬으로 정확히 수행되는지 여부를 판단하는 근거가 된다.
프로세서가 메모리를 참조하는 경우에는 읽기와 쓰기가 있다. 읽기는 특정 데이터를 메모리로부터 가져오는 동작이고 쓰기는 특정 데이터를 만들어 메모리에 가져다 놓는 동작이다. 따라서 읽기의 경우 해당 데이터가 없으면 프로세서가 더이상 프로그램을 진행시킬 수 없는 반면 쓰기의 경우 프로세서는 반드시 쓰기가 끝날 때까지 기다릴 필요가 없다. 후자의 경우 특정 하드웨어가 쓰기에 필요한 데이터를 받아 여유가 생길 때 메모리에 쓰기를 하면 될 것이다.
이렇게 함으로써 프로세서는 쓰기에 필요한 시간을 기다릴 필요없이 다른 명령어들을 수행할 수 있다. 이같이 쓰기에 수반될 지연을 쓰기버퍼(Write Buffer)라는 하드웨어로 해결할 수 있다. 읽기도 성능향상을 위해 특수한 하드웨어와 기법을 사용한다. 예컨대 명령어 버퍼라는 것을 이용해 수행할 명령어들을 프로세서 내부에 미리 가져다 놓음으로써 프로그램 수행시간을 단축시키기도 하는 것이다.
프로세서를 개념적으로 가정해 보자. 프로그램의 명령어들이 실제로 수행되는 순서는 「프로그램 명령(Program Order)」이고 프로그램이 가정하는 데이터 참조 순서는 「생성 명령(Issuing Order)」에 나타나는 읽기와 쓰기 순서다. 하지만 프로세서 밖에서 보기에는 메모리 참조가 「액세스 명령(Access Order)」에 나타난 순서로 진행될 것이다. 주목할 점은 쓰기버퍼가 있으므로 생성 명령에 나타난 읽기와 쓰기 순서가 액세스 명령에는 다르게 나타날 수 있다는 것이다. 더구나 다른 프로세서는 액세스 명령에 나타난 순서와 다르게 관측할 수 있다.
이러한 현상이 시사하는 점은 프로그램 작성자가 생각하는 프로그램의 명령어 실행 순서와 메모리 참조를 통해 나타나는 실행 순서, 그리고 다른 프로세서가 관측한 실행 순서가 다를 수 있다는 것이다. 더구나 다양한 최적화 기법을 구사하는 컴파일러는 프로그램에서 정의한 명령어 수행 순서와는 다르게 명령어를 재배치하기도 하므로 앞서 설명한 하드웨어적으로 순서가 변하는 것보다 더욱 복잡한 경우가 발생할 수 있다.
일반적으로 통용되는 메모리모델은 읽기에 의해 받은 값은 같은 주소에 대해 프로그램에서 정의된 순서에 따라 가장 최근에 씌어진 값이 되고, 쓰기 값은 같은 주소에 대한 다음 쓰기가 있을 때까지 해당 메모리 주소에 대한 읽기 값으로 된다. 즉 같은 번지에 대해 순차적인 읽기와 쓰기가 보장되는 것을 가정하는 것이다. 이러한 모델은 흔히 메모리/캐시 동일성(Memory/Cache Coherency) 유지에 관한 정의로 알려져 있다.
과거의 단일 프로세서 컴퓨터에서는 메모리 참조 동작이 한번에 하나씩 수행되고 그 순서도 프로그램에서 규정된 대로 진행된다고 볼 수 있었다. 그러나 요즈음의 고성능 프로세서는 메모리 참조 동작을 중첩하여 수행하거나 프로그램에서 정의된 순서를 벗어나 수행하는 것을 허용하기도 한다. 그러나 단일 프로세서 컴퓨터에서는 데이터와 제어 종속관계를 유지함으로써 프로그램 작성자가 가정한 순차적 메모리 참조를 수행하는 것과 동일한 메모리모델을 유지할 수 있다. 바꾸어 말하면 단일 프로세서 시스템에서는 데이터와 제어 종속관계를 유지하는 이상 하드웨어와 컴파일러가 메모리 참조 동작을 프로그램 순서와 다르게 발생시키거나 수행할 수 있다.
다중 프로세서 시스템에서는 한 메모리 주소에 대한 여러 읽기와 여러 쓰기가 동시에 진행될 수 있기 때문에 언제 읽기가 완료됐거나 쓰기가 완료됐는지, 그리고 이들간의 순서를 명확하게 구별하기 힘든 경우가 발생한다. 서로 다른 두 프로세서가 같은 주소에 대해 동시에 쓰기를 하고 이어 그 주소에 대해 읽기를 했다고 가정하자. 이때 각 프로세서는 쓰기를 자신의 쓰기버퍼에만 하게 되고 이어지는 읽기는 각 쓰기버퍼에 있는 값을 읽게 될 것이다. 이 경우 각 프로세서가 보는 메모리 참조 순서는 전혀 다르게 된다. 이같이 같은 주소에 대해 순서가 유지되기 어렵지만 서로 다른 주소에 대해 일관된 순서를 유지하기란 더욱 어렵다.
메모리모델이 지켜지지 않을 경우 프로그램이 의도한 바와 다르게 수행될 수 있다. 따라서 프로그램 작성자는 프로그램이 수행될 컴퓨터의 정확한 메모리모델을 이해해 그에 맞게 프로그램을 작성해야 한다. 이제까지 다양한 메모리모델이 제안됐고 또한 쓰이고 있다. 보다 정확히 말하자면 컴퓨터마다 그 나름의 메모리모델이 있다고 할 수 있다. 그러나 각 메모리모델이 상당한 차이를 보일 수도 있고 단지 미묘한 차이가 있는 것도 있다. 여기에서는 읽기와 쓰기만으로 설명될 수 있는 두 모델을 살펴본다.
우선 SC(Sequential Consistency)모델이다. 이 모델은 프로세서가 쓰기를 할 때 메모리 쓰기가 완전히 끝날 때까지 기다릴 필요없이 단지 쓰기버퍼에만 쓰고 끝나는 것을 허용하지만 읽기는 반드시 해당 데이터가 올 때까지 기다린다. 특히 읽기는 쓰기버퍼에 처리되지 못한 쓰기가 남아 있는 경우 쓰기버퍼가 빌 때까지 기다려야 한다. 쓰기버퍼에 있는 쓰기들은 한번에 하나씩 처리돼야 한다. 이러한 동작을 가능케 하는 충분조건은 첫째, 다른 프로세서에 대해 읽기가 수행되기에 앞서 해당 프로세서의 프로그램에 의해 선행된 모든 읽기와 쓰기들이 완전히 실행돼야 한다. 둘째, 다른 프로세서에 대해 쓰기가 수행되기에 앞서 해당 프로세서의 프로그램에 의해 선행된 모든 읽기와 쓰기들이 완전히 실행돼야 한다.
PC(Processor Consistency)모델은 모든 것이 SC와 동일하지만 예외로 동일 주소가 아닌 이상 쓰기버퍼에 남아있는 쓰기들보다 먼저 읽기가 진행될 수 있다. 이러한 동작을 가능케 하는 충분조건은 첫째, 다른 프로세서에 대해 읽기가 수행되기에 앞서 해당 프로세서의 프로그램에 의해 선행된 모든 읽기들이 완전히 실행돼야 한다. 둘째, 다른 프로세서에 대해 쓰기가 수행되기에 앞서 해당 프로세서의 프로그램에 의해 선행된 모든 읽기와 쓰기들이 완전히 실행돼야 한다.
이들 두 모델의 차이는 읽기가 쓰기를 추월하여 실행될 수 있느냐 없느냐에 있다. SC에서는 프로세서가 발생시킨 메모리 참조(읽기와 쓰기) 동작이 정확히 프로그램에서 규정한 순서로 진행되고 이 순서가 다른 프로세서가 관측하는 순서가 된다. 다시 말해 생성 명령에 나타난 읽기와 쓰기 순서가 액세스 명령에 동일하게 나타난다. PC모델에서는 프로세서가 발생시킨 메모리 참조 동작 중 쓰기만큼은 정확히 프로그램에서 규정한 순서로 진행되고 이 순서가 다른 프로세서에서 관측하는 순서가 된다. 즉 생성 명령에 나타난 쓰기 순서가 액세스 명령에 동일하게 나타나지만 읽기의 경우는 다를 수 있는 것을 허용한다. 따라서 SC보다 PC모델쪽이 자유도가 높고 더욱 느슨하며 성능향상 가능성도 높다.
하지만 메모리/캐시 동일성 유지만으로는 SC 요건을 만족시키지 못한다. 왜냐하면 「같은 주소에 대한 쓰기만을 모든 프로세서에 동일한 순서로 보이게 하는 것」만으로는 SC가 요구하는 다음 두가지 요건을 보장하지 못하기 때문이다. 첫째, 모든 주소에 대한 모든 쓰기가 모든 프로세서에 동일한 순서로 보여야 하며, 둘째, 한 프로세서의 모든 메모리 참조 동작이 프로그램 순서대로 보여야 한다. 이러한 점은 메모리/캐시 동일성 유지만으로는 메모리모델을 정확히 규정할 수 없다는 점을 말한다.
SC와 PC 메모리모델 이외에 더욱 느슨한 모델로는 WO(Weak Ordering)모델, RC(Release Consistency)모델 등이 있다. 이들은 여러 쓰기가 동시에 진행되는 것을 허용하며 추가로 읽기도 동시에 여럿이 진행되는 것을 허용하여 읽기와 쓰기에 대한 실행순서에 자유도가 높다. 주의할 점은 느슨한 메모리모델을 사용할 경우 프로그램 작성자 또는 컴파일러는 보다 확실히 프로그램을 이해해 정말 순서가 지켜져야 되는 부분을 정확히 구분해야 된다. 왜냐하며 덜 느슨한 메모리모델을 가정하여 작성한 프로그램은 이보다 더 느슨한 메모리모델을 제공하는 컴퓨터에서는 프로그램 작성자가 원하는 결과를 얻지 못할 수도 있기 때문이다. 즉 SC을 가정해 작성한 프로그램은 이보다 느슨한 모델인 PC, WO, RC모델에서 오류를 초래할 수 있다.
이러한 이유로 최근의 마이크로프로세서들은 FENCE, MB(Memory Barrier), STBAR(STore BARrier), FLUSH 등 메모리 참조 순서를 강제로 제어하는 명령어들을 제공한다. 인텔 펜티엄프로는 PC모델을 지원하고, DEC 알파와 IBM 파워PC는 RC모델과 유사한 모델을 지원한다. SPARC는 TSO(Total Store Ordering), PST(Partial Store Ordering), RMO(Relaxed Memory Ordering)모델들을 지원하는데 이들은 각각 PC, WO, RC모델과 유사하다.
이제까지 대부분의 프로그램 작성자는 SC보다 더 경직된 메모리모델을 기본으로 생각해 프로그램을 작성했다. 그러나 이러한 모델은 쓰기버퍼라든가 명령어 재배치 등과 같은 하드웨어적 그리고 소프트웨어적인 성능증가 기법을 사용하는 데 많은 제약으로 작용했다.
성능향상만을 고려한다면 가능한 한 느슨한 메모리모델이 유리하겠지만 이 경우 소프트웨어 작성에 커다란 부담을 주게 되며 또한 기존의 많은 프로그램과 알고리듬이 수정돼야 한다. 그러나 고성능 컴퓨터 기술에서는 보다 유연한(느슨한) 메모리모델을 사용해 좀더 성능이 우수한 프로그램 실행환경을 채택하게 될 것이다.