동시성(Concurrency)와 병렬성(Parallelism)
OCaml이 멀티 코어를 통해 더 나은 지원을 하려 노력하는 두 가지 중요한 계산 방법이 있다.
- 동시성(Concurrency)은 여러 계산을 분할해서 엄격하게 순차적으로
실행하는 되는 것이 아니라, 겹치는 시간(overlapping time)에 실행할
수 있도록 하는 방법이다. OCaml은 하나의 힙에 대해서는 이미
Lwt
나Async
같은 훌륭한 라이브러리들이 있다. OCaml의Thread
모듈 역시 동시성 계산을 표현하기 위한 훌륭한 방법이다. - 병렬성(Parallelism)은 여러 계산을, 주로 멀티코어 머신의 여러 개의 코어를 이용해서 동시에 실행하는 방법이다.
OCaml에는 동시성과 병렬성을 지원하는 여러 메커니즘들이 존재한다.
시스템 | 동시성 | 병렬성 |
---|---|---|
OCaml 4.11 Thread 모듈
| 직접적인 스타일(Direct-style)의 코드를 동시에 실행할 수 있음, pthreads 사용
| OCaml 런타임 락으로 인해, C 쓰레드가 병렬적으로 실행되긴 하지만 최종적으로는 하나의 OCaml 쓰레드로 합쳐짐 |
Lwt / Async
| 모나드 스타일(monadic interface)로 코드를 짜야 함 | 싱글 쓰레드이지만 입출력을 병렬로 할 수 있음 |
Functory
| map 처럼 Functory 모듈 스타일로 동시성 연산을 짜야 함
| 여러 개의 런타임에서 동작하며, 분산 처리도 가능 |
이런 방법들은 여러 개의 코어에서 병렬적으로 OCaml 코드가 실행되는 직접적인 스타일의 동시성을 지원하지 않는다. 멀티코어 OCaml 프로젝트는 이러한 한계를 해결하고 직접적인 스타일로 작성된 OCaml 코드가 공유 메모리 병렬성(Shared-Memory Parallelism; SMP)을 허용하는 것을 목표로 한다.
도메인과 파이버, 이펙트
현재 멀티코어에서 동시성과 병렬성에 대한 추상화 구현체는 두 가지가 있다.
- 도메인은 병렬적으로 실행되며, 자신만의 마이너 힙을 가지고 멀티코어 마이너/메이저 GC를 관리하는데 필요한 동기화가 필요하기 때문에 상당히 무겁다. domainslib 라이브러리를 사용하면 도메인을 이용해서 병렬 계산을 쉽게 할 수 있다.
- (이펙트를 통해 제공되는) 파이버는 유연한 동시성을 허용하는 동적 스택을 갖고 있는 가벼운 실행 문맥이다. 파이버는 이펙트를 통해서 만들어지고 관리된다(scheduled). 도메인끼리 컨티뉴이에션을 주고 받을 수 있어서 멀티코어 런타임 위에서 복잡한 스케쥴링이 가능하다.
참조
- 도메인은 블로킹 연산에 대해서는 블록된다. 구체적으로, 다른 계산의 스케쥴링이 멈춘다.
- 블로킹 연산이 호출되면 도메인도 블록되기 때문에, 만약 파이버가 블로킹 C 연산을 호출하면 해당 도메인에서 수행되는 모든 스케쥴링은 이 연산이 끝날 때까지 블록된다.
- 멀티코어 GC는 도메인 개수가 물리적 코어의 개수보다 작거나 같을 때 가장 잘 동작하도록 설계되었다. 런타임이 가비지 콜렉터를 관리하기 위해 도메인마다 추가적인 상태를 갖기 때문이다. 마이너 콜렉션과 메이저 싸이클의 끝에서 도메인들끼리 동기화가 필요하다. 그러므로, 도메인이 시스템 (p)쓰레드와 짝지어지긴 하지만, OCaml에서는 더 무거운 추상화로 취급된다.