주의 : 이 문서는 초심자 튜토리얼이 아닙니다. 기본 개념 정도는 안다고 가정합니다. 초심자는 [ Vulkan Tutorial ] 이나 [ Vulkan Samples Tutorial ] 을 보면서 같이 보시기 바랍니다.

주의 : 완전히 이해하고 작성한 글이 아니므로 잘못된 내용이 포함되어 있을 수 있습니다.

주의 : 이상하면 참고자료를 확인하세요.



Vulkan 명세의 [ 2.6. Threading Behavior ] 에서는 다음과 같이 이야기하고 있습니다.


Vulkan 은 다중 호스트 스레드를 사용할 때 확장가능한 성능을 제공하도록 설계되어 있습니다. 모든 커맨드들은 다중 스레드에서 동시적으로 호출되도록 지원하고 있습니다. 하지만 특정 파라미터나 파라미터의 요소들은 외부적으로 동기화되도록( externally synchronized ) 정의되어 있습니다. 이는 호출자가 그런 파라미터를 동시에 하나 이상의 스레드에서만 호출되도록 보장해야만 한다는 것을 의미합니다.


좀 더 정확하게 이야기하자면, Vulkan 커맨드들은 Vulkan 오브젝트의 상태를 갱신하기 위한 단순한 저장소( simple stores )들을 사용합니다. 외부적으로 동기화되도록 선언된 파라미터들은 호스트가 커맨드를 실행하는 동안에 언제든 갱신될 수 있습니다. 만약 같은 오브젝트에 대해 동작하는 두 개의 커맨드가 있는데, 둘 중의 하나라도 외부적으로 동기화되도록 오브젝트를 선언했다면, 호출자는 커맨드들이 동시적으로 실행되지 않도록 보장해야할 뿐만 아니라, 그 두 개의 커맨드들이 ( 필요하다면 ) 적절한 메모리 배리어에 의해서 분리되도록 보장해야만 합니다.


요약하자면, Vulkan 은 커맨드를 다중의 스레드에서 실행함으로써 동시성을 보장한다는 것입니다. 하지만 외부 동기화를 요구하는 파라미터( externally synchronized parameter )들을 사용하는 커맨드들은 동시에 실행되서는 안 된다는거죠. 


매우 단순한 예를 하나 들어 보겠습니다. 버퍼 A 와 A 에 쓰기 작업을 하는 두 개의 스레드가 존재한다고 합시다. 그리고 각각의 스레드에서는 개별적으로 커맨드들을 생성했다고 가정하겠습니다. 그러면 각각의 스레드에서 생성한 커맨드들은 서로 관계가 없으므로 동시적으로 실행될 수 있습니다. 하지만 A 에 동시에 쓰기를 할 수는 없겠죠. 그러므로 이런 커맨드들이 동시적으로 실행되지 않도록 보장해 줄 필요가 있습니다.


External Synchronization


"외부적으로 동기화된다( externally synchronized )" 는 의미는 상당히 혼란스럽습니다. 저로서는 상당히 생소한 개념인데요, 일단 구글링을 해 봤습니다. 


그런데 이 용어 자체에 대해서 근본적으로 설명하는 글들은 없고, 대부분이 "Clock Synchronization" 혹은 "Time Synchronization" 에 대한 글들이더군요.


[ 1 ] 에 의하면 internal synchronization 과 external synchronization 의 차이는 다음과 같습니다.


분산 시스템에서 클락 동기화는 보통 하나나 두 개의 목적을 가집니다: (1) 분산 시스템을 구성하는 모든 노드들이 같은 내부 시계( clock )을 소유하는 것을 보장하고, (2) 그 분산 시스템이 다른 외부 시계와 동기화되는 것을 보장합니다.


내부 동기화는 보통 컴퓨팅 클러스터들이 자신들의 로컬 시계들로 동기화되도록 허용하는 동기화 프로토콜을 통해서 수행됩니다. 그 머신은 공통 시간을 사용한다고 동의하는거죠. 하지만, 이 그들이 동의한 시간은 외부 시계와 동기화될 필요는 없습니다. 예를 들면 특정 타임존( time-zone )에 대해서 말이죠.


외부 동기화는 컴퓨팅 시스템들이 NTP 프로토콜을 사용하여 제공되는 서버와 같은 외부 시간에 자신들의 시계가 동기화되도록 만듭니다. 이것의 목적은 컴퓨팅 시스템의 시간을 특정 타임존과 동기화시키는 것입니다. 만약 정확한 시간이 요구된다면, 원자 시계( atomic clock )으로부터 시간을 생성하는 NTP 시스템들이 사용됩니다.


두 경우 모두, NTP 프로토콜이 사용될 수 있으며, 광범위하게 사용됩니다.


결국 Vulkan 명세에서 이야기하는 외부 동기화는 이런 의미가 아니라는 것을 알 수 있습니다. 좀 더 구글링을 해 보니, 다음과 같은 질문이 있었습니다[ 2 ].


컬렉션 프레임워크( collection framework )에서, 왜 외부 동기화가 내부 동기화( Vector, HashTable 등 )보다 빠른가요? 심지어는 같은 메커니즘을 사용함에도 불구하구요?


정확히 내부 동기화와 외부 동기화의 의미가 무엇이며, 그것들이 왜 다른가요?


누가 예제를 가지고 설명해 주면 정말 도움이 될 것 같네요.


답변에서는 외부 동기화에 대해 다음과 같이 설명하고 있더군요.


외부 동기화는 호출자가 synchronized 키워드나 lock 을 사용해서 다중 스레드에서 접근되는 다른 클래스를 보호하는 것을 의미합니다. 이것은 보통 클래스가 자체적으로 동기화되지 않을 때 사용됩니다.


즉 Vulkan 에서의 "외부 동기화"는 오브젝트의 동기화를 오브젝트 외부에서 보장해야 한다는 것을 의미한다고 볼 수 있습니다. 


예를 들자면, 버퍼 A 는 자체적인 동기화 기능을 가지고 있지 않기 때문에, 쓰기 커맨드가 다른 스레드에서 동시에 실행되지 않도록 외부에서 동기화해 줘야 한다는 겁니다. 또한 생성되면 다시는 수정되지 않는 immutable( non-writable ) 속성의 오브젝트들도 다른 스레드에서 사용중일 때 파괴되지 않도록 외부 동기화를 해 줘야만 합니다.


Internal Synchronization


명세에 의하면 어떤 오브젝트들은 내부 동기화를 사용한다고 합니다. 예를 들면 vkCreateGraphicsPipelines() 과 vkCreateComputePipelines() 에서의 VkPipelineCache 파라미터가 있습니다. 이 경우에는 외부 동기화를 하는게 무겁기 때문에 내부 동기화를 한다고 하는군요.


커맨드 파라미터에 대해서 명시적으로 "외부 동기화된다"고 적혀 있지 않다면, 해당 파라미터들은 내부 동기화를 한다고 합니다.


Implicit External Synchronization


명세에 의하면 동기화해야 할 오브젝트가 한 종류 더 있습니다. 묵시적인 외부 동기화인데요, 이 경우는 커맨드의 파라미터와 연관되어 있는 오브젝트들에 대한 외부 동기화를 의미합니다. 예를 들면 Command Pool 과 Descriptor Pool 이 있습니다.


Which objects are externally synchronized?


이제 내부 동기화와 외부 동기화의 개념에 대해서 알게 되었습니다. 하지만 어떤 오브젝트가 외부 동기화되는지 알 수 있을까요?


기본적으로 외부 동기화되거나 묵시적으로 외부 동기화되는 커맨드나 오브젝트의 리스트는 [ 2.6. Threading Behavior ] 섹션에서 찾아볼 수 있습니다. "Externally Synchronized Parameters", "Externally Synchronized Parameter Lists", "Implicit Externally Synchronized Parameters" 라는 항목들에서 그 리스트를 볼 수 있습니다.



물론 이 리스트를 뽑아 놓고 지금 파라미터가 동기화되어야 하는지 찾아 보는 방법도 있지만, 특정 함수에 대해서 동기화 여부를 찾아 볼 수도 있습니다.


예를 들어 "Externally Synchronized Parameters" 리스트에 있는 vkDestroyInstance() 명세에 가보면 "Host Synchronization" 이라는 항목을 볼 수 있습니다.



만약 동기화가 필요하다면 "Host Synchronization" 항목이 반드시 있으므로 이를 확인하시면 됩니다.


정리


Vulkan 오브젝트들은 일부 오브젝트를 제외하고는 외부 동기화를 요구하게 됩니다. VkPipelineCache 같은 특정 오브젝트를 제외한 대부분의 오브젝트가 자체적인 동기화 기능을 내장하고 있지 않으므로, 반드시 외부에서 동기화를 해 줘야 합니다.


외부 동기화의 실례는 다음 글에서 다루도록 하겠습니다.


참고자료


[ 1 ] What is the difference between internal clock synchronization and external clock synchronization in distributed systems?, stack overflow.


[ 2 ] why external synchronization is faster than internal one?, stack overflow.


[ 3 ] Vulkan Specification 1.1, Khronos Group.

+ Recent posts