Ray
Ray는 parallel and distributed application 제작을 위한 universal API 입니다. 머신러닝 엔지니어링에서 필요한 확장가능한 시스템을 구축할 수 있도록 하며, 효과적이고 단순하게 분산/병렬 컴퓨팅을 수행할 수 있게 도와줍니다. 이러한 강점으로 아직 정확한 체계가 잡히지 못한 머신러닝 엔지니어링이라는 분야의 초석이 되기에 부족함이 없는 강력한 도구입니다.
-
최근에 핫한 라이브러리로 머신러닝/딥러닝을 위해 개발되었지만 다양하게 활용할 수 있음
- 기존에 작성한 코드를 조금만 추가해서 병렬처리를 할 수 있는 점이 큰 장점!
- Ray Core를 기반으로 여러 애플리케이션 존재. 대규모 에코 시스템 구축
주요 컨셉
Ray 는 dynamic task graph computation model 로 구현되어 있습니다. 이 모델은 크게 Task
와 Actor
라는 2가지 추상화 타입으로 제공됩니다. state 의 유무가 가장 큰 차이를 나타냅니다.
- Task 는 stateless worker 의 remote 함수 실행을 의미합니다. multiprocessing 모듈과 비슷한 역할을 수행합니다. (실제로는 다르지만..) ‘함수’ 의 역할과 대응됩니다.
- Actor 는 state 를 저장하는 계산을 의미합니다. (stateful actor) ‘클래스’ 의 역할과 대응 됩니다.
Ray 의 Task 와 Actor 모델
Task 와 Actor 모두 ‘worker’ 로 ray 에서는 remote 함수를 통해 실행할 수 있습니다. remote 함수는 파이썬 객체 대신 future 를 리턴하며 이 값은 다른 remote 함수의 인자로 사용할 수 있습니다.
Worker 를 자세히 이해하기 위해서는 Ray 의 아키텍처를 이해하면 좋습니다.
크게는 system layer 와 app layer, 2개의 파트로 구성됩니다. Application layer 는 API 와 계산 모델을 구현하고 system layer 는 backend 로써 task 의 스케쥴링과 데이터 관리를 수행합니다.
Task 실행 시 아키텍쳐에서 동작 흐름을 살펴보면 driver(user program) 에서 작성된 ray 함수와 GCS 의 table 에 등록하고 스케쥴러를 작성합니다. 작성된 스케쥴을 system layer 에서 global scheduler 로 관리되며 객체에 대한 정보도 GCS table 에 등록됩니다. 실제 동작할 worker 에서는 global 스케쥴러와 GCS 에 등록된 execution / object 를 받아와서 작업을 수행하게 됩니다.
처음 Ray를 접할 때는 크게 Task, Actor, Object, Driver, Job 정도만 이해해도 충분함
(그 이후에 내부가 궁금하면 Node, Worker, Scheduler, Global Control Store 등에 대해 파악해보기)
Task(Remote Function)
- 호출하는 곳과 다른 프로세스에서 실행되는 함수
- 함수를 @ray.remote로 감싼 경우를 Task라 지칭
- Remote Function이라고 부르는 경우도 있음
- 호출할 경우 Task가 비동기(asynchoronously)하게 실행됨
.remote()
를 호출하면 Future 객체(ObjectRef)를 반환ray.get(ObjectRef)
를 할 경우 Task가 실행됨- @ray.remote로 감싼 함수의 경우 stateless하고, @ray.remote로 감싼 클래스(Actor)의 Task는 stateful함
- 사용 방식
- 함수를 작성하고(예 : say_hello 함수)
- 함수에 데코레이터로 @ray.remote로 감싸고
- 함수 호출은 say_hello.remote()
- 값 반환은 ray.get(say_hello.remote())
Actor
- Stateful한 워커
- @ray.remote로 감싼 파이썬 클래스 인스턴스
Object
- 어플리케이션의 value
- Task를 통해 반환되거나
ray.put()
을 통해 생성- 사용 예시 : Pandas 데이터프레임을 Object로 만들어서 Ray 워커에서 사용하곤 함
- Object는 immutable하며 한번 생성되면 수정되지 않음(스파크의 RDD처럼)
Driver
- 프로그램의 메인 루트
ray.init()
을 호출하면 실행
Job
- 동일한 드라이버에서 발생한 Task, Actor, Object의 컬렉션
자주 사용하는 API 정리
- 위에서 설명하진 않았지만 알아두면 좋은
ray.put()
,ray.wait()
,ray.shutdown()
도 정리함 - 참고로 ray.put()는 큰 배열을 공유 메모리에 저장하고 복사본을 만들지 않고 모든 작업자에 프로세스에 액세스 할 수 있음
- 복사를 하지 않으니 메모리를 아낄 수 있음
Ray 사용 Tip
###