๐Ÿ’ป AI Software

ExecuTorch Compiler ์ƒ์„ธ

๊ฐœ์š”

ExecuTorch ์ปดํŒŒ์ผ๋Ÿฌ๋Š” PyTorch ๋ชจ๋ธ์„ ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์—์„œ ํšจ์œจ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” .pte ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ •์ (AOT) ์ปดํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋‹ค. ๊ธฐ์กด Backend ๋ฌธ์„œ๊ฐ€ ๋ฐฑ์—”๋“œ ์‹œ์Šคํ…œ๊ณผ ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์ดˆ์ ์„ ๋งž์ถ˜ ๋ฐ˜๋ฉด, ๋ณธ ๋ฌธ์„œ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋‚ด๋ถ€ ๋™์ž‘์— ์ง‘์ค‘ํ•œ๋‹ค.

ExecuTorch ์ปดํŒŒ์ผ๋Ÿฌ์˜ ํ•ต์‹ฌ์€ EXIR(ExecuTorch Intermediate Representation)์ด๋ผ๋Š” ์ค‘๊ฐ„ ํ‘œํ˜„ ์ฒด๊ณ„์ด๋‹ค. ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ โ†’ Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ โ†’ Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋กœ ์ด์–ด์ง€๋Š” 3๋‹จ๊ณ„ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ๋ณ€ํ™˜์„ ํ†ตํ•ด, ์‚ฌ์šฉ์ž ๋ชจ๋ธ์„ ํ•˜๋“œ์›จ์–ด์— ์ตœ์ ํ™”๋œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ๋‚ฎ์ถ”(lowering)๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์ด๋‹ค. ์ด ๊ณผ์ •์—์„œ ์ปค์Šคํ…€ ์ปดํŒŒ์ผ๋Ÿฌ ํŒจ์Šค, ์—ฐ์‚ฐ ์œตํ•ฉ, ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹, ์ฝ”๋“œ ์ƒ์„ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ์ตœ์ ํ™”๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…

EXIR ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ์ฒด๊ณ„

EXIR Dialect Hierarchy

ExecuTorch๋Š” ๋ชจ๋ธ์„ ๋‹จ๊ณ„์ ์œผ๋กœ ๋‚ฎ์ถ”๊ธฐ ์œ„ํ•ด ์„ธ ๊ฐ€์ง€ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค:

๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ๋‹จ๊ณ„ ํŠน์ง• ์—ฐ์‚ฐ์ž ์„ธํŠธ
ATen 1๋‹จ๊ณ„ PyTorch eager ๋ชจ๋ธ์˜ ๊ฐ€์žฅ ์ถฉ์‹คํ•œ ์บก์ฒ˜ torch.ops.aten ๋„ค์ž„์ŠคํŽ˜์ด์Šค
Edge 2๋‹จ๊ณ„ ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์— ์œ ์šฉํ•œ ํŠนํ™” (ํ•˜๋“œ์›จ์–ด ๋…๋ฆฝ์ ) dtype ํŠนํ™”๋œ Edge ์—ฐ์‚ฐ์ž
Backend 3๋‹จ๊ณ„ ํ•˜๋“œ์›จ์–ด๋ณ„ ํƒ€๊ฒŸ ์—ฐ์‚ฐ์ž, ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ํ†ตํ•ฉ ๋ฐฑ์—”๋“œ ์ „์šฉ ์—ฐ์‚ฐ์ž

ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ

ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋Š” torch.export()์˜ ์ง์ ‘์ ์ธ ์ถœ๋ ฅ์œผ๋กœ, eager ๋ชจ๋“œ PyTorch ํ”„๋กœ๊ทธ๋žจ์ด Exported IR ๊ทธ๋ž˜ํ”„๊ฐ€ ๋˜๋Š” ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์ด๋‹ค:

import torch

# ๋ชจ๋ธ ์ •์˜
model = MyModel().eval()
example_inputs = (torch.randn(1, 3, 224, 224),)

# Export โ†’ ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ
aten_program = torch.export.export(model, example_inputs)

ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ์†์„ฑ:
- ๊ธฐ๋Šฅํ™”(functionalization)๊ฐ€ ์ˆ˜ํ–‰๋˜์–ด ํ…์„œ ๋ณ„์นญ(alias)๊ณผ ๋ณ€์ด(mutation)๊ฐ€ ์ œ๊ฑฐ๋จ
- ๋ชจ๋“  ์—ฐ์‚ฐ์ž๋Š” torch.ops.aten ๋„ค์ž„์ŠคํŽ˜์ด์Šค์˜ ATen ์—ฐ์‚ฐ์ž์ด๊ฑฐ๋‚˜ ๋“ฑ๋ก๋œ ์ปค์Šคํ…€ ์—ฐ์‚ฐ์ž
- ๋ชจ๋“  ์—ฐ์‚ฐ์ž์— meta kernel์ด ์žˆ์–ด์•ผ ํ•จ (์ž…๋ ฅ shape์œผ๋กœ ์ถœ๋ ฅ shape ์ถ”๋ก )
- ๋ชจ๋“  ํ…์„œ๋Š” torch.contiguous_format ๋ฉ”๋ชจ๋ฆฌ ํฌ๋งท ์‚ฌ์šฉ
- ๋™์  dtype, ์•”๋ฌต์  dtype ํ”„๋กœ๋ชจ์…˜, ์•”๋ฌต์  ๋ธŒ๋กœ๋“œ์บ์ŠคํŒ… ์ง€์›

Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ

Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋Š” ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์— ์œ ์šฉํ•˜์ง€๋งŒ ํ•˜๋“œ์›จ์–ด์— ์•„์ง ํŠนํ™”๋˜์ง€ ์•Š์€ ์ค‘๊ฐ„ ๋‹จ๊ณ„์ด๋‹ค:

from executorch import exir

# ATen โ†’ Edge ๋ณ€ํ™˜
edge_program: exir.EdgeProgramManager = exir.to_edge(aten_program)

Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ์†์„ฑ:
- ๋ชจ๋“  ์—ฐ์‚ฐ์ž๋Š” dtype ํŠนํ™”๋œ Edge ์—ฐ์‚ฐ์ž (ํ•˜๋“œ์›จ์–ด ๋…๋ฆฝ์ )
- ๋ชจ๋“  Scalar ํƒ€์ž…์€ Tensor๋กœ ๋ณ€ํ™˜
- edge.yaml์— dtype ์ œ์•ฝ ์กฐ๊ฑด ์ •์˜
- ์ปค์Šคํ…€ ๊ทธ๋ž˜ํ”„ ๋ณ€ํ™˜(Pass) ์ ์šฉ ๊ฐ€๋Šฅ

dtype ์ œ์•ฝ ์กฐ๊ฑด ์˜ˆ์‹œ:

- func: sigmoid
  namespace: edge
  inherits: aten::sigmoid
  type_alias:
    T0: [Bool, Byte, Char, Int, Long, Short]
    T1: [Double, Float]
    T2: [Float]
  type_constraint:
  - self: T0
    __ret_0: T2
  - self: T1
    __ret_0: T1

Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ

Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋Š” ์„ ํƒ์  ๋‹จ๊ณ„๋กœ, ๋ฐฑ์—”๋“œ๊ฐ€ ๊ทธ๋ž˜ํ”„๋ฅผ ํ•˜๋“œ์›จ์–ด๋ณ„ ์—ฐ์‚ฐ์ž, ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ, ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ๋œ ๋กœ์–ด ๋ชจ๋“ˆ๋กœ ์žฌ์ž‘์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค:

# Edge โ†’ Backend ๋ณ€ํ™˜ (๋ฐฑ์—”๋“œ๋ณ„ ํŒŒํ‹ฐ์…”๋„ˆ ์‚ฌ์šฉ)
program = to_edge_transform_and_lower(
    aten_program,
    partitioner=[XnnpackPartitioner()]
).to_executorch()

Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ํŠน์ง•:
- Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ ์ดํ›„์—๋งŒ ์‹คํ–‰
- ํ•˜๋“œ์›จ์–ด๋ณ„ ์œตํ•ฉ, ๋กœ์–ด๋ง ํŒจํ„ด, ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ํ†ตํ•ฉ์— ์‚ฌ์šฉ
- ์ปค์Šคํ…€ ์—ฐ์‚ฐ์ž์™€ ๋‹ฌ๋ฆฌ ๋ฐฑ์—”๋“œ ์ „์šฉ ์—ฐ์‚ฐ์ž๋Š” ์ด ๋‹จ๊ณ„์—์„œ๋งŒ ๋„์ž…

์ปค์Šคํ…€ ์ปดํŒŒ์ผ๋Ÿฌ ํŒจ์Šค

ExecuTorch๋Š” ๊ทธ๋ž˜ํ”„ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ ๋‹ค์–‘ํ•œ ์ปค์Šคํ…€ ํŒจ์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค:

ํŒจ์Šค ๋ถ„๋ฅ˜ ์ฒด๊ณ„:

์ถ• ๊ตฌ๋ถ„ ์˜ˆ์‹œ
๋งคํ•‘ ์œ ํ˜• 1-to-X (๋ถ„ํ•ด) ์—ฐ์‚ฐ์ž ๋ถ„ํ•ด
Many-to-1 (์œตํ•ฉ) ์—ฐ์‚ฐ์ž ์œตํ•ฉ
๋ฐ˜๋ณต ๋ฐฉํ–ฅ ์ˆœ๋ฐฉํ–ฅ (shape ์ „ํŒŒ) shape ์ถ”๋ก 
์—ญ๋ฐฉํ–ฅ (์ฝ”๋“œ ์ œ๊ฑฐ) ์ฃฝ์€ ์ฝ”๋“œ ์ œ๊ฑฐ
์ •๋ณด ์˜์กด์„ฑ ๋กœ์ปฌ ๋…ธ๋“œ ์ •๋ณด out-variant ๋ณ€ํ™˜
๊ธ€๋กœ๋ฒŒ ๊ทธ๋ž˜ํ”„ ์ •๋ณด ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹

ExportPass (Level 1 ํŒจ์Šค):

from executorch.exir.pass_base import ExportPass

class ReplaceInPlaceReluWithOutOfPlaceReluPass(ExportPass):
    """in-place relu_๋ฅผ out-of-place relu๋กœ ๊ต์ฒด"""

    def call_operator(self, op, args, kwargs, meta):
        if op != torch.ops.aten.relu_.default:
            return super().call_operator(op, args, kwargs, meta)
        return super().call_operator(
            Op(torch.ops.aten.relu.default), args, kwargs, meta
        )

# ํŒจ์Šค ์‹คํ–‰
replace_pass = ReplaceInPlaceReluWithOutOfPlaceReluPass()
new_graph_module = replace_pass(graph_module).graph_module

Subgraph Rewriter (Level 2 ํŒจ์Šค):

from torch.fx import subgraph_rewriter

def replace_patterns(graph_module):
    def pattern(x, y):
        x = torch.ops.aten.add.Tensor(x, y)
        x = torch.ops.aten.mul.Tensor(x, y)
        return x

    def replacement(x, y):
        return torch.ops.aten.sub.Tensor(x, y)

    return subgraph_rewriter.replace_pattern_with_filters(
        graph_module, pattern, replacement
    )

ํŒŒํ‹ฐ์…”๋„ˆ

ํŒŒํ‹ฐ์…”๋„ˆ๋Š” ๋ชจ๋ธ ๊ทธ๋ž˜ํ”„๋ฅผ ํ•˜๋“œ์›จ์–ด ์ง€์› ์„œ๋ธŒ๊ทธ๋ž˜ํ”„์™€ CPU ํด๋ฐฑ์œผ๋กœ ๋ถ„ํ• ํ•œ๋‹ค:

ํŒŒํ‹ฐ์…”๋„ˆ ์œ ํ˜• ์„ค๋ช… ์‚ฌ์šฉ ์‚ฌ๋ก€
Subgraph Matcher ํŒจํ„ด ๊ธฐ๋ฐ˜ ์„œ๋ธŒ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ํŠน์ • ์—ฐ์‚ฐ์ž ์กฐํ•ฉ ํƒ์ง€
Capability-Based ์ง€์›๋˜๋Š” ์—ฐ์‚ฐ์ž ๊ธฐ๋ฐ˜ ๋ถ„ํ•  ํ•˜๋“œ์›จ์–ด ์ง€์› ๋ฒ”์œ„ ๊ธฐ๋ฐ˜ ๋ถ„ํ• 
Source Partitioner ์†Œ์Šค ์ˆ˜์ค€ ๋ชจ๋“ˆ ๋ถ„ํ•  torch.nn.Linear ๋“ฑ ๊ณ ์ˆ˜์ค€ ๋ชจ๋“ˆ ํƒ์ง€
from torch.fx.passes.infra.partitioner import CapabilityBasedPartitioner
from torch.fx.passes.operator_support import OperatorSupportBase

class AddMulOperatorSupport(OperatorSupportBase):
    def is_node_supported(self, submodules, node: torch.fx.Node) -> bool:
        return node.op == "call_function" and node.target in [
            torch.ops.aten.add.Tensor,
            torch.ops.aten.mul.Tensor,
        ]

partitioner = CapabilityBasedPartitioner(graph_module, AddMulOperatorSupport())
partitions = partitioner.propose_partitions()

๋™์ž‘ ์›๋ฆฌ

์ „์ฒด ์ปดํŒŒ์ผ๋Ÿฌ ํŒŒ์ดํ”„๋ผ์ธ

ExecuTorch Compiler Pipeline

ExecuTorch ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์€ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๊ตฌ์„ฑ๋œ๋‹ค:

1๋‹จ๊ณ„: ๋ชจ๋ธ ์บก์ฒ˜ (torch.export)

import torch
from executorch.exir import to_edge_transform_and_lower

# eager ๋ชจ๋“œ ๋ชจ๋ธ ์ •์˜
model = MyModel().eval()
example_inputs = (torch.randn(1, 3, 224, 224),)

# Export โ†’ ATen ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ
aten_program = torch.export.export(model, example_inputs)

2๋‹จ๊ณ„: ์—ฃ์ง€ ๋ณ€ํ™˜ (to_edge)

# ATen โ†’ Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ
# dtype ํŠนํ™”, Scalar โ†’ Tensor ๋ณ€ํ™˜ ์ˆ˜ํ–‰
edge_program = exir.to_edge(aten_program)

3๋‹จ๊ณ„: ๊ทธ๋ž˜ํ”„ ์ตœ์ ํ™” (์ปค์Šคํ…€ ํŒจ์Šค)

# ์ปค์Šคํ…€ ํŒจ์Šค๋ฅผ ํ†ตํ•œ ๊ทธ๋ž˜ํ”„ ๋ณ€ํ™˜
edge_program = edge_program.transform(MyCustomPass())

4๋‹จ๊ณ„: ํ•˜๋“œ์›จ์–ด ๋กœ์–ด๋ง (to_backend)

# ํŒŒํ‹ฐ์…”๋„ˆ๋ฅผ ํ†ตํ•œ ๊ทธ๋ž˜ํ”„ ๋ถ„ํ•  ๋ฐ ๋ฐฑ์—”๋“œ ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ
program = to_edge_transform_and_lower(
    aten_program,
    partitioner=[XnnpackPartitioner()]
)

5๋‹จ๊ณ„: ExecuTorch ํ”„๋กœ๊ทธ๋žจ ์ƒ์„ฑ (to_executorch)

# Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ โ†’ .pte ํŒŒ์ผ ์ƒ์„ฑ
executorch_program = program.to_executorch()

๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹

ExecuTorch ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์‹คํ–‰ ์‹œ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์„ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ •์  ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹์„ ์ˆ˜ํ–‰ํ•œ๋‹ค:

ํ”Œ๋ž˜๋‹ ๋‹จ๊ณ„ ์„ค๋ช…
ํ…์„œ ์ˆ˜๋ช… ๋ถ„์„ ๊ฐ ํ…์„œ์˜ ์ƒ๋ช… ์ฃผ๊ธฐ ๊ณ„์‚ฐ
๋ฒ„ํผ ๊ณต์œ  ๋™์‹œ์— ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ํ…์„œ ๊ฐ„ ๋ฉ”๋ชจ๋ฆฌ ๊ณต์œ 
๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ ๊ฒฐ์ • ์‹คํ–‰ ์‹œ ํ• ๋‹นํ•  ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ ๊ฒฐ์ •
ํฌ๊ธฐ ๊ณ„์‚ฐ ์ด ํ•„์š”ํ•œ ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ ์‚ฐ์ •

์ฝ”๋“œ ์ƒ์„ฑ

Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ์—์„œ .pte ํŒŒ์ผ๋กœ ๋ณ€ํ™˜๋  ๋•Œ, ExecuTorch๋Š” ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค:

์ƒ์„ฑ ์š”์†Œ ์„ค๋ช…
์—ฐ์‚ฐ์ž ์ปค๋„ ํ˜ธ์ถœ ๊ฐ ์—ฐ์‚ฐ์ž์— ๋Œ€ํ•œ ์ปค๋„ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ฝ”๋“œ
ํ…์„œ ๋””์Šคํฌ๋ฆฝํ„ฐ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ๋ฐ ๋ ˆ์ด์•„์›ƒ ์ •๋ณด
๋ฉ”์„œ๋“œ ํ…Œ์ด๋ธ” ๋ชจ๋ธ์˜ ๊ฐ ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์‹คํ–‰ ์ •๋ณด
์ƒ์ˆ˜ ๊ฐ€์ค‘์น˜ ๋ชจ๋ธ ๊ฐ€์ค‘์น˜์˜ ์ง๋ ฌํ™”๋œ ๋ฐ์ดํ„ฐ
ํ”Œ๋žซ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท ๋””๋ฐ”์ด์Šค์—์„œ ์ง์ ‘ ํŒŒ์‹ฑ ๊ฐ€๋Šฅํ•œ ํ˜•์‹

.pte ํŒŒ์ผ ๊ตฌ์กฐ

.pte ํŒŒ์ผ ๊ตฌ์กฐ:
โ”œโ”€โ”€ ํ—ค๋” (magic number, ๋ฒ„์ „, ์ฒดํฌ์„ฌ)
โ”œโ”€โ”€ ์„ธ๊ทธ๋จผํŠธ ํ…Œ์ด๋ธ”
โ”‚   โ”œโ”€โ”€ ํ”„๋กœ๊ทธ๋žจ ์„ธ๊ทธ๋จผํŠธ (๊ทธ๋ž˜ํ”„ ๊ตฌ์กฐ)
โ”‚   โ”œโ”€โ”€ ์ปค๋„ ์„ธ๊ทธ๋จผํŠธ (์—ฐ์‚ฐ์ž ๊ตฌํ˜„)
โ”‚   โ””โ”€โ”€ ๋ฐ์ดํ„ฐ ์„ธ๊ทธ๋จผํŠธ (๊ฐ€์ค‘์น˜)
โ”œโ”€โ”€ ๋ฉ”์„œ๋“œ ๋””์Šคํฌ๋ฆฝํ„ฐ
โ”‚   โ”œโ”€โ”€ ์ž…๋ ฅ/์ถœ๋ ฅ ์‚ฌ์–‘
โ”‚   โ”œโ”€โ”€ ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹ ์ •๋ณด
โ”‚   โ””โ”€โ”€ ์‹คํ–‰ ์ˆœ์„œ
โ””โ”€โ”€ ๋ฐฑ์—”๋“œ ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ์ •๋ณด

๋น„๊ต/๋ถ„์„

์ปดํŒŒ์ผ๋Ÿฌ ํŒŒ์ดํ”„๋ผ์ธ ๋น„๊ต

ํŠน์„ฑ ExecuTorch TensorRT ONNX Runtime TFLite
์ปดํŒŒ์ผ ๋ฐฉ์‹ AOT (Export IR) AOT (Layer Fusion) AOT (ONNX Graph) AOT (FlatBuffer)
์ค‘๊ฐ„ ํ‘œํ˜„ EXIR (3๋‹จ๊ณ„ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ) TensorRT Engine ONNX Graph TFLite Model
์ตœ์ ํ™” ๋‹จ๊ณ„ Export โ†’ Edge โ†’ Backend โ†’ .pte Parser โ†’ Fusion โ†’ Tuning Graph Opt โ†’ Execution Converter โ†’ Optimizer
๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹ ์ •์  (์ปดํŒŒ์ผ ์‹œ) ์ •์  ์ •์  ์ •์ 
๋ฐฑ์—”๋“œ ํ†ตํ•ฉ ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ์‹œ์Šคํ…œ ๋„ค์ดํ‹ฐ๋ธŒ ํ†ตํ•ฉ Execution Provider Delegate

์ปค์Šคํ…€ ํŒจ์Šค ํ”„๋ ˆ์ž„์›Œํฌ ๋น„๊ต

๊ธฐ๋Šฅ ExecuTorch (ExportPass) TVM (MetaSchedule) XLA (HLO Pass)
ํŒจ์Šค ์œ ํ˜• ์ธํ„ฐํ”„๋ฆฌํ„ฐ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰ ๊ธฐ๋ฐ˜ ๊ทธ๋ž˜ํ”„ ๊ธฐ๋ฐ˜
๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ณด์กด ์™„์ „ ์ง€์› ๋ถ€๋ถ„ ์ง€์› ๋ถ€๋ถ„ ์ง€์›
IR Spec ์ค€์ˆ˜ ํŒจ์Šค ์ „ํ›„ ๊ฒ€์ฆ ๊ฒ€์ฆ ๋ถˆํ•„์š” ๊ฒ€์ฆ ๋ถˆํ•„์š”
์ปค์Šคํ…€ ํŒจ์Šค ์ž‘์„ฑ ExportPass ์ƒ์† Pass ๊ธฐ๋ฐ˜ HLO Pass ๊ธฐ๋ฐ˜
์ž๋™ ํŠœ๋‹ ๋ฏธ์ง€์› (MetaSchedule) ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ œํ•œ์ 

์ฝ”๋“œ ์ƒ์„ฑ ์ „๋žต ๋น„๊ต

์ „๋žต ExecuTorch TensorRT ONNX Runtime
๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•์‹ FlatBuffer (.pte) ์ปค์Šคํ…€ ์—”์ง„ (.engine) FlatBuffer (.ort)
์ปค๋„ ํ†ตํ•ฉ ๋Ÿฐํƒ€์ž„ ์—ฐ๊ฒฐ ์ •์  ์—ฐ๊ฒฐ ๋™์  ๋กœ๋“œ
ํฌ๊ธฐ ์ตœ์ ํ™” ์ƒ์ˆ˜ ์••์ถ•, ์„ธ๊ทธ๋จผํŠธ ๋ถ„๋ฆฌ ๋Ÿฐํƒ€์ž„ ์ตœ์ ํ™” ๊ทธ๋ž˜ํ”„ ์ตœ์ ํ™”
์‹คํ–‰ ๋ชจ๋ธ ์ธํ„ฐํ”„๋ฆฌํ„ฐ + ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ JIT ์ปดํŒŒ์ผ ์„ธ์…˜ ๊ธฐ๋ฐ˜

์žฅ๋‹จ์ 

์žฅ์ 

  1. ๋‹จ๊ณ„์  ๋กœ์–ด๋ง (Progressive Lowering): ATen โ†’ Edge โ†’ Backend 3๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด ์ ์ง„์ ์œผ๋กœ ํ•˜๋“œ์›จ์–ด์— ํŠนํ™”๋˜์–ด, ๊ฐ ๋‹จ๊ณ„์—์„œ ๋…๋ฆฝ์ ์ธ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค
  2. IR Spec ๊ธฐ๋ฐ˜ ๊ฒ€์ฆ: ๊ฐ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ์—์„œ IR Spec์„ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ๊ฒ€์ฆํ•˜์—ฌ, ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋‹ค
  3. ์œ ์—ฐํ•œ ์ปค์Šคํ…€ ํŒจ์Šค: ExportPass, Subgraph Rewriter ๋“ฑ ๋‹ค์–‘ํ•œ ์ˆ˜์ค€์˜ ํŒจ์Šค๋ฅผ ์ œ๊ณตํ•˜์—ฌ ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ธ๋ฐ€ํ•œ ๊ทธ๋ž˜ํ”„ ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค
  4. ์ •์  ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹: ์‹คํ–‰ ์‹œ ๋™์  ํ• ๋‹น ์—†์ด ๋ฏธ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ณ„ํšํ•˜์—ฌ, ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์—์„œ ๋ถˆํ•„์š”ํ•œ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค
  5. ์ดˆ๊ฒฝ๋Ÿ‰ .pte ํŒŒ์ผ: FlatBuffer ๊ธฐ๋ฐ˜์˜ ํ”Œ๋žซ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ, ํŒŒ์‹ฑ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์ตœ์†Œํ™”๋œ๋‹ค

๋‹จ์ 

  1. ์ปดํŒŒ์ผ ์‹œ๊ฐ„: AOT ์ปดํŒŒ์ผ ๋ฐฉ์‹์œผ๋กœ ์ธํ•ด ๋Œ€๊ทœ๋ชจ ๋ชจ๋ธ์—์„œ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค
  2. ์ปค์Šคํ…€ ์ปค๋„ ์ œ์•ฝ: EXIR ์—ฐ์‚ฐ์ž ์„ธํŠธ ์™ธ์˜ ์ปค์Šคํ…€ ์ปค๋„์€ ๋ณ„๋„ ๋“ฑ๋ก์ด ํ•„์š”ํ•˜๋ฉฐ, Edge ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ์—์„œ์˜ dtype ์ œ์•ฝ์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•œ๋‹ค
  3. ๋™์  Shape ์ œํ•œ: ์ •์  ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹ ํŠน์„ฑ์ƒ ๋™์  shape ์ง€์›์ด ์ œํ•œ์ ์ด๋‹ค
  4. ํ•™์Šต ๋ฏธ์ง€์›: ์ถ”๋ก  ์ „์šฉ ์ปดํŒŒ์ผ๋Ÿฌ๋กœ, ํ•™์Šต ๊ทธ๋ž˜ํ”„๋Š” ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค
  5. ๋””๋ฒ„๊น… ์–ด๋ ค์›€: AOT ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ ๊ทธ๋ž˜ํ”„ ๋ณ€ํ™˜์ด ๋‹ค์ˆ˜ ๋ฐœ์ƒํ•˜์—ฌ, ์›๋ณธ ๋ชจ๋ธ๊ณผ์˜ ๋Œ€์‘ ๊ด€๊ณ„ ์ถ”์ ์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ๋‹ค

๊ด€๋ จ ๊ธฐ์ˆ 

๊ธฐ์ˆ  ๊ด€๊ณ„ ์„ค๋ช…
PyTorch Export ์ƒ์œ„ API torch.export()๋กœ ๋ชจ๋ธ ๊ทธ๋ž˜ํ”„ ์บก์ฒ˜
EXIR ์ค‘๊ฐ„ ํ‘œํ˜„ ExecuTorch์˜ IR ์ฒด๊ณ„ (ATen/Edge/Backend ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ)
FX Graph ๊ทธ๋ž˜ํ”„ ํ”„๋ ˆ์ž„์›Œํฌ PyTorch์˜ FX ๊ธฐ๋ฐ˜ ๊ทธ๋ž˜ํ”„ representation
torchao ์–‘์žํ™” ExecuTorch์˜ ์–‘์žํ™” ํŒŒ์ดํ”„๋ผ์ธ ํ†ตํ•ฉ
XNNPACK ๊ธฐ๋ณธ ๋ฐฑ์—”๋“œ ๋ชจ๋“  ํ”Œ๋žซํผ์—์„œ CPU ํด๋ฐฑ์œผ๋กœ ์‚ฌ์šฉ
FlatBuffer ์ง๋ ฌํ™” .pte ํŒŒ์ผ์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ํ˜•์‹

์ฐธ๊ณ  ๋ฌธํ—Œ

ํ•ต์‹ฌ ์ •๋ฆฌ

  1. ExecuTorch ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ATen โ†’ Edge โ†’ Backend 3๋‹จ๊ณ„ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ๋ฅผ ํ†ตํ•ด ๋ชจ๋ธ์„ ์ ์ง„์ ์œผ๋กœ ๋‚ฎ์ถ”๋Š” AOT ์ปดํŒŒ์ผ ์‹œ์Šคํ…œ์ด๋‹ค.
  2. EXIR์€ ๊ฐ ๋‹ค์ด์–ด๋ ‰ํ‹ฐ๋ธŒ์—์„œ IR Spec์„ ์ค€์ˆ˜ํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด, ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ์˜ ์˜ค๋ฅ˜๋ฅผ ์กฐ๊ธฐ์— ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. ExportPass, Subgraph Rewriter ๋“ฑ ๋‹ค์–‘ํ•œ ์ปค์Šคํ…€ ํŒจ์Šค๋ฅผ ํ†ตํ•ด ๊ทธ๋ž˜ํ”„ ์ˆ˜์ค€์˜ ์„ธ๋ฐ€ํ•œ ์ตœ์ ํ™”๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
  4. ์ •์  ๋ฉ”๋ชจ๋ฆฌ ํ”Œ๋ž˜๋‹๊ณผ FlatBuffer ๊ธฐ๋ฐ˜ .pte ํŒŒ์ผ ์ƒ์„ฑ์œผ๋กœ ์—ฃ์ง€ ๋””๋ฐ”์ด์Šค์— ์ตœ์ ํ™”๋œ ์‹คํ–‰ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•œ๋‹ค.
  5. 12๊ฐœ ์ด์ƒ์˜ ํ•˜๋“œ์›จ์–ด ๋ฐฑ์—”๋“œ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋”œ๋ฆฌ๊ฒŒ์ดํŠธ ์‹œ์Šคํ…œ์„ ํ†ตํ•ด ํ•˜๋“œ์›จ์–ด ์ „ํ™˜์ด ์šฉ์ดํ•˜๋‹ค.