https://blog.kc-ml2.com/tvm/

내용 원문 및 사진 출처는 https://tvm.apache.org/docs/dev/relay_intro.html 에 있습니다.

Build a computational graph with relay

DL 프레임워크들은 IR로 DAG 형식의 computational graph(=data flow graph)를 사용합니다. 이는 간단해서 automatic differentiation를 구현하거나 heterogeneous 환경에서 컴파일하기(어떤 부분들은 어디에서 실행하고 등등...) 쉽습니다. TVM에서도 Relay를 사용하여 computational graph를 만듭니다.

2-node-graph 만들기

2-node-graph 만들기

위 그림을 사용해서 relay의 특징에 대해 계속 설명을 이어가겠습니다.

Module: Support Multiple Functions (Graphs)

위에서는 function을 통해 data flow graph를 만드는 방법을 알아보았습니다. 이제는 더 넓은 시야에서, function을 여러 개 만들고, 이들이 서로를 참조할 수 있는 방법에 대해 알아봅시다.

Relay는 여러개의 function을 갖는 module이라는 데이터 구조를 가지고 있습니다.

def @muladd(%x, %y, %z) {
  %1 = mul(%x, %y)
  %2 = add(%1, %z)
  %2
}
def @myfunc(%x) {
  %1 = @muladd(%x, 1, 2)
  %2 = @muladd(%1, 2, 3)
  %2
}

Module은 (GlobalVar, Function)들의 집합이라고 이해할 수 있습니다. GlobalVar은 모듈 내 함수의 id라고 보면 됩니다. 위 예시에서는 @muladd@myfunc가 되겠군요. CallNode를 사용해서 다른 함수를 부를 때, op field에서 GlobalVar를 통해 그 함수를 호출하면 됩니다. GlobalVar를 사용하면 함수의 definition과 declaration을 분리시켜 recursion이나 delayed declaration 등을 가능하게 해 줍니다.

def @myfunc(%x) {
  %1 = equal(%x, 1)
   if (%1) {
      %x
   } else {
     %2 = sub(%x, 1)
     %3 = @myfunc(%2)
      %4 = add(%3, %3)
      %4
  }
}

Let Bindings and Scopes

let binding은 high-level programming language에서 사용됩니다. 걸어둔 링크에 따르면, let binding을 다음과 같이 설명하고 있습니다.