Aproveitando UMA para disponibilizar aceleradores de hardware diretamente para TVM

Este artigo foi traduzido do documento em inglês Preparando seu acelerador de hardware para TVM com UMA

Os autores são Michael J. Klaiber , Christoph Gerum , Paul Palomero Bernardo .

Mais documentos da TVM em chinês podem ser acessados ​​→ TVM Chinese Station

Esta seção apresenta a Universal Modular Accelerator Interface (UMA). A UMA fornece uma API fácil de usar para integrar novos aceleradores de hardware ao TVM.

Este tutorial detalha como usar UMA para disponibilizar seu acelerador de hardware diretamente para TVM. Embora não haja uma solução única para esse problema, a UMA pretende fornecer uma API Python pura e estável para integrar vários tipos de aceleradores de hardware ao TVM.

Este tutorial apresentará a API UMA por meio de três casos de uso de complexidade crescente. Esses casos de uso apresentam três aceleradores de simulação Vanilla, Strawberry e Chocolate e os integram ao TVM usando UMA.

baunilha

Vanilla é um acelerador simples que consiste em uma matriz de MACs e não possui memória interna. Ele só pode lidar com a camada Conv2D, todas as outras camadas são executadas na CPU, enquanto também coordenam o vanilla. CPU e Vanilla compartilham memória.

A interface C do Vanilla vanilla_conv2dnchw(…) é usada para executar operações Conv2D (incluindo o mesmo preenchimento), recebe ponteiros para o mapa de recursos de entrada, pesos e resultados e as dimensões do Conv2D: oc, iw, ih, ic, kh e kw .

int vanilla_conv2dnchw(float* ifmap, float*  weights, float*  result, int oc, int iw, int ih, int ic, int kh, int kw);

O script uma_cli cria esqueletos de código com chamadas de API (UMA-API) para novos aceleradores.

Vanilla é usado assim: (–tutorial vanilla adiciona todos os arquivos adicionais necessários para esta parte do tutorial)

pip install inflection
cd $TVM_HOME/apps/uma
python uma_cli.py --add_hardware vanilla_accelerator --tutorial vanilla

uma_cli.py gera esses arquivos no diretório vanilla_accelerator.

backend.py
codegen.py
conv2dnchw.cc
passes.py
patterns.py
run.py
strategies.py

Vanilla back-end

O back-end gerado pelo vanilla está localizado em vanilla_accelerator/backend.py :

class VanillaAcceleratorBackend(UMABackend):
 """VanillaAccelerator 的 UMA 后端。"""

 def __init__(self):
 super().__init__()

        self._register_pattern("conv2d", conv2d_pattern())
        self._register_tir_pass(PassPhase.TIR_PHASE_0, VanillaAcceleratorConv2DPass())
        self._register_codegen(fmt="c", includes=gen_includes)

 @property
 def target_name(self):
 return "vanilla_accelerator"

Definir o padrão de migração

Para especificar a migração Conv2D para Vanilla, ela é descrita em vanilla_accelerator/patterns.py como um padrão de fluxo de dados de retransmissão (DFPattern).

def conv2d_pattern():
    pattern = is_op("nn.conv2d")(wildcard(), wildcard())
    pattern = pattern.has_attr({"strides": [1, 1]})
 return pattern

Para mapear o operador Conv2D do gráfico de cálculo de entrada para a chamada de função subjacente do Vanilla vanilla_conv2dnchw(...), o passe TIR VanillaAcceleratorConv2DPass é registrado no VanillaAcceleratorBackend (discutido posteriormente).

Codegen

O arquivo vanilla_accelerator/codegen.py define o código C estático que é adicionado ao código C resultante gerado pelo C-Codegen da TVM em gen_includes com o propósito de incluir vanilla_conv2dnchw(), a biblioteca subjacente para Vanilla.

def gen_includes() -> str:
    topdir = pathlib.Path(__file__).parent.absolute()

    includes = ""
    includes += f'#include "{topdir}/conv2dnchw.cc"'
 return includes

Conforme mostrado no VanillaAcceleratorBackend acima, ele pode ser registrado com o UMA usando self._register_codegen.

self._register_codegen(fmt="c", includes=gen_includes)

Construir uma rede neural e executá-la no vanilla

Para demonstrar os recursos do UMA, o código C é gerado para uma única camada Conv2D e executado em um acelerador de baunilha. O arquivo vanilla_accelerator/run.py fornece uma demonstração da execução de uma camada Conv2D usando a API C do Vanilla.

def main():
    mod, inputs, output_list, runner = create_conv2d()

    uma_backend = VanillaAcceleratorBackend()
    uma_backend.register()
    mod = uma_backend.partition(mod)
    target = tvm.target.Target("vanilla_accelerator", host=tvm.target.Target("c"))

    export_directory = tvm.contrib.utils.tempdir(keep_for_debug=True).path
 print(f"Generated files are in {export_directory}")
    compile_and_run(
        AOTModel(module=mod, inputs=inputs, outputs=output_list),
        runner,
        interface_api="c",
        use_unpacked_api=True,
        target=target,
        test_dir=str(export_directory),
 )

main()

Executar vanilla_accelerator/run.py irá gerar arquivos de saída em Model Library Format (MLF).

Resultado de saída:

Generated files are in /tmp/tvm-debug-mode-tempdirs/2022-07-13T13-26-22___x5u76h0p/00000

Confira os arquivos gerados:

Resultado de saída:

cd /tmp/tvm-debug-mode-tempdirs/2022-07-13T13-26-22___x5u76h0p/00000
cd build/
ls -1

codegen
lib.tar
metadata.json
parameters
runtime
src

Para avaliar o código C gerado, consulte codegen/host/src/default_lib2.c.

cd codegen/host/src/
ls -1

default_lib0.c
default_lib1.c
default_lib2.c

Em default_lib2.c, você pode ver que o código gerado chama a C-API do Vanilla e então executa uma camada Conv2D:

TVM_DLL int32_t tvmgen_default_vanilla_accelerator_main_0(float* placeholder, float* placeholder1, float* conv2d_nchw, uint8_t* global_workspace_1_var) {
 vanilla_accelerator_conv2dnchw(placeholder, placeholder1, conv2d_nchw, 32, 14, 14, 32, 3, 3);
 return 0;
}

morango

em breve

chocolate

em breve

Busque informações da comunidade

Se este tutorial não for adequado para o seu acelerador, adicione seus requisitos ao tópico UMA no fórum TVM. Ficaríamos felizes em estender este tutorial para fornecer mais orientações, por exemplo, como aproveitar a interface UMA para disponibilizar uma variedade maior de aceleradores de hardware AI diretamente para TVM.

Referência
[ UMA-RFC] UMA: Universal Modular Accelerator Interface , TVM RFC, junho de 2022.

[DFPattern] Correspondência de padrões no Relay

Baixe o código-fonte do Python: uma.py

Baixe o Jupyter Notebook: uma.ipynb

O texto acima é todo o conteúdo do documento, clique para ver mais documentos da TVM em chinês .

Guess you like

Origin blog.csdn.net/HyperAI/article/details/130079396