MLIR 개요 — 왜 여러 레벨의 IR이 필요한가
MLIR 개요 — 왜 여러 레벨의 IR이 필요한가
딥러닝 컴파일러를 생각해 보면, 텐서 연산 같은 높은 수준의 그래프와 실제 하드웨어가 이해하는 어셈블리 사이엔 큰 간격이 있어요. 이 간격을 메우기 위해 여러 레벨의 중간 표현을 둘 필요가 있는데, MLIR 은 이 아이디어를 하나의 IR 안에 여러 레벨이 공존하는 구조로 구현한 프로젝트예요.
MLIR은 노드와 엣지로 된 연산(Operation) 과 값(Value) 의 그래프 구조를 기본으로 해요. 각 값은 정확히 하나의 연산 또는 블록 인자의 결과이고, 연산은 블록(Block) 안에, 블록은 영역(Region) 안에 들어가는 계층 구조를 가져요. 덕분에 함수 정의나 버퍼 할당부터 타깃 전용 명령, 레지스터 설정까지 아주 다양한 개념을 같은 틀로 표현할 수 있어요.
레벨을 구분 짓는 핵심은 다이얼렉트(dialect) 라는 확장 메커니즘이에요. 예를 들어 Affine 다이얼렉트는 affine 네임스페이스로 폴리헤드럴 루프 최적화 개념을, LLVM 다이얼렉트는 LLVM IR 하위 구조를 담당해요. 여러 다이얼렉트가 한 모듈 안에 공존할 수 있고, 다이얼렉트 변환(Dialect Conversion) 프레임워크로 서로 변환해요.
연산에 대한 변환은 pass 로 수행하고, 연산의 의미를 추상화해 주는 Trait과 Interface를 통해 pass가 특정 연산에 얽매이지 않고 범용적으로 동작하게 해요. 사람이 읽는 텍스트 형태, 메모리 안의 프로그래매틱 형태, 저장·전송용 직렬화 형태가 모두 같은 의미를 표현해요.