LiteRT Next를 사용한 GPU 가속

그래픽 처리 장치 (GPU)는 CPU에 비해 대규모 병렬 처리량이 많기 때문에 일반적으로 딥 러닝 가속화에 사용됩니다. LiteRT Next는 사용자가 컴파일된 모델(CompiledModel)을 만들 때 하드웨어 가속을 매개변수로 지정할 수 있도록 허용하여 GPU 가속을 사용하는 프로세스를 간소화합니다. LiteRT Next는 LiteRT에서 제공하지 않는 새로운 개선된 GPU 가속 구현도 사용합니다.

LiteRT Next의 GPU 가속을 사용하면 GPU 친화적인 입력 및 출력 버퍼를 만들고, GPU 메모리의 데이터로 제로 복사를 실행하고, 작업을 비동기식으로 실행하여 동시 실행을 극대화할 수 있습니다.

GPU 지원이 포함된 LiteRT Next 구현의 예는 다음 데모 애플리케이션을 참고하세요.

GPU 종속 항목 추가

다음 단계에 따라 Kotlin 또는 C++ 애플리케이션에 GPU 종속 항목을 추가합니다.

Kotlin

Kotlin 사용자의 경우 GPU 가속기가 내장되어 있으며 시작하기 가이드 외의 추가 단계가 필요하지 않습니다.

C++

C++ 사용자의 경우 LiteRT GPU 가속으로 애플리케이션의 종속 항목을 빌드해야 합니다. 핵심 애플리케이션 로직을 패키징하는 cc_binary 규칙(예: main.cc)에는 다음과 같은 런타임 구성요소가 필요합니다.

  • LiteRT C API 공유 라이브러리: data 속성에는 LiteRT C API 공유 라이브러리 (//litert/c:litert_runtime_c_api_shared_lib)와 GPU별 구성요소(@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so)가 포함되어야 합니다.
  • 속성 종속 항목: deps 속성에는 일반적으로 GLES 종속 항목 gles_deps()이 포함되며 linkopts에는 일반적으로 gles_linkopts()가 포함됩니다. LiteRT는 Android에서 OpenGLES를 사용하는 경우가 많으므로 두 가지 모두 GPU 가속과 밀접한 관련이 있습니다.
  • 모델 파일 및 기타 애셋: data 속성을 통해 포함됩니다.

다음은 cc_binary 규칙의 예시입니다.

cc_binary(
    name = "your_application",
    srcs = [
        "main.cc",
    ],
    data = [
        ...
        # litert c api shared library
        "//litert/c:litert_runtime_c_api_shared_lib",
        # GPU accelerator shared library
        "@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so",
    ],
    linkopts = select({
        "@org_tensorflow//tensorflow:android": ["-landroid"],
        "//conditions:default": [],
    }) + gles_linkopts(), # gles link options
    deps = [
        ...
        "//litert/cc:litert_tensor_buffer", # litert cc library
        ...
    ] + gles_deps(), # gles dependencies
)

이 설정을 사용하면 컴파일된 바이너리가 GPU를 동적으로 로드하고 가속된 머신러닝 추론에 사용할 수 있습니다.

시작하기

GPU 가속기를 사용하려면 컴파일된 모델 (CompiledModel)을 만들 때 GPU 매개변수를 전달합니다. 다음 코드 스니펫은 전체 프로세스의 기본 구현을 보여줍니다.

C++

// 1. Load model
LITERT_ASSIGN_OR_RETURN(auto model, Model::CreateFromFile("mymodel.tflite"));

// 2. Create a compiled model targeting GPU
LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model, CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// 3. Prepare input/output buffers
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// 4. Fill input data (if you have CPU-based data)
input_buffers[0].Write<float>(absl::MakeConstSpan(cpu_data, data_size));

// 5. Execute
compiled_model.Run(input_buffers, output_buffers);

// 6. Access model output
std::vector<float> data(output_data_size);
output_buffers.Read<float>(absl::MakeSpan(data));

Kotlin

// Load model and initialize runtime
val  model =
    CompiledModel.create(
        context.assets,
        "mymodel.tflite",
        CompiledModel.Options(Accelerator.GPU),
        env,
    )

// Preallocate input/output buffers
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

// Fill the first input
inputBuffers[0].writeFloat(FloatArray(data_size) { data_value /* your data */ })

// Invoke
model.run(inputBuffers, outputBuffers)

// Read the output
val outputFloatArray = outputBuffers[0].readFloat()

자세한 내용은 C++ 시작하기 또는 Kotlin 시작하기 가이드를 참고하세요.

LiteRT Next GPU 가속기

LiteRT Next에서만 사용할 수 있는 새로운 GPU 가속기는 대규모 행렬 곱셈, LLM용 KV 캐시와 같은 AI 워크로드를 이전 버전보다 효율적으로 처리하도록 최적화되었습니다. LiteRT Next GPU 가속기에는 LiteRT 버전보다 다음과 같은 주요 개선사항이 있습니다.

  • 확장된 연산자 적용 범위: 더 크고 복잡한 신경망을 처리합니다.
  • 더 나은 버퍼 상호 운용성: 카메라 프레임, 2D 텍스처 또는 대규모 LLM 상태에 GPU 버퍼를 직접 사용할 수 있습니다.
  • 비동기 실행 지원: CPU 전처리를 GPU 추론과 겹칩니다.

GPU 가속을 사용한 제로 복사

제로 복사를 사용하면 CPU가 데이터를 명시적으로 복사하지 않아도 GPU가 자체 메모리의 데이터에 직접 액세스할 수 있습니다. 제로 복사는 데이터를 CPU 메모리로 복사하거나 CPU 메모리에서 복사하지 않으므로 엔드 투 엔드 지연 시간을 크게 줄일 수 있습니다.

다음 코드는 벡터 그래픽 렌더링을 위한 API인 OpenGL을 사용한 제로 복사 GPU의 구현 예입니다. 코드는 OpenGL 버퍼 형식의 이미지를 LiteRT Next에 직접 전달합니다.

// Suppose you have an OpenGL buffer consisting of:
// target (GLenum), id (GLuint), size_bytes (size_t), and offset (size_t)
// Load model and compile for GPU
LITERT_ASSIGN_OR_RETURN(auto model, Model::CreateFromFile("mymodel.tflite"));
LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// Create a TensorBuffer that wraps the OpenGL buffer.
LITERT_ASSIGN_OR_RETURN(auto tensor_type, model.GetInputTensorType("input_tensor_name"));
LITERT_ASSIGN_OR_RETURN(auto gl_input_buffer, TensorBuffer::CreateFromGlBuffer(env,
    tensor_type, opengl_buffer.target, opengl_buffer.id, opengl_buffer.size_bytes, opengl_buffer.offset));
std::vector<TensorBuffer> input_buffers{gl_input_buffer};
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// Execute
compiled_model.Run(input_buffers, output_buffers);

// If your output is also GPU-backed, you can fetch an OpenCL buffer or re-wrap it as an OpenGL buffer:
LITERT_ASSIGN_OR_RETURN(auto out_cl_buffer, output_buffers[0].GetOpenClBuffer());

비동기 실행

RunAsync()와 같은 LiteRT의 비동기 메서드를 사용하면 CPU 또는 NPU를 사용하여 다른 작업을 계속하는 동안 GPU 추론을 예약할 수 있습니다. 복잡한 파이프라인에서는 GPU가 CPU 또는 NPU와 함께 비동기식으로 사용되는 경우가 많습니다.

다음 코드 스니펫은 제로 복사 GPU 가속 예에 제공된 코드를 기반으로 합니다. 이 코드는 CPU와 GPU를 비동기식으로 모두 사용하고 LiteRT Event를 입력 버퍼에 연결합니다. LiteRT Event는 다양한 유형의 동기화 원시를 관리하며 다음 코드는 LiteRtEventTypeEglSyncFence 유형의 관리형 LiteRT 이벤트 객체를 만듭니다. 이 Event 객체는 GPU가 완료될 때까지 입력 버퍼에서 읽지 않도록 합니다. 이 모든 작업은 CPU를 사용하지 않고 실행됩니다.

LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create({}));
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
    CompiledModel::Create(env, model, kLiteRtHwAcceleratorGpu));

// 1. Prepare input buffer (OpenGL buffer)
LITERT_ASSIGN_OR_RETURN(auto gl_input,
    TensorBuffer::CreateFromGlBuffer(env, tensor_type, opengl_tex));
std::vector<TensorBuffer> inputs{gl_input};
LITERT_ASSIGN_OR_RETURN(auto outputs, compiled_model.CreateOutputBuffers());

// 2. If the GL buffer is in use, create and set an event object to synchronize with the GPU.
LITERT_ASSIGN_OR_RETURN(auto input_event,
    Event::CreateManagedEvent(env, LiteRtEventTypeEglSyncFence));
inputs[0].SetEvent(std::move(input_event));

// 3. Kick off the GPU inference
compiled_model.RunAsync(inputs, outputs);

// 4. Meanwhile, do other CPU work...
// CPU Stays busy ..

// 5. Access model output
std::vector<float> data(output_data_size);
outputs[0].Read<float>(absl::MakeSpan(data));

지원되는 모델

LiteRT Next는 다음 모델에서 GPU 가속을 지원합니다. 벤치마크 결과는 삼성 갤럭시 S24 기기에서 실행된 테스트를 기반으로 합니다.

모델 LiteRT GPU 가속 LiteRT GPU (ms)
hf_mms_300m 완전히 위임됨 19.6
hf_mobilevit_small 완전히 위임됨 8.7
hf_mobilevit_small_e2e 완전히 위임됨 8.0
hf_wav2vec2_base_960h 완전히 위임됨 9.1
hf_wav2vec2_base_960h_dynamic 완전히 위임됨 9.8
isnet 완전히 위임됨 43.1
timm_efficientnet 완전히 위임됨 3.7
timm_nfnet 완전히 위임됨 9.7
timm_regnety_120 완전히 위임됨 12.1
torchaudio_deepspeech 완전히 위임됨 4.6
torchaudio_wav2letter 완전히 위임됨 4.8
torchvision_alexnet 완전히 위임됨 3.3
torchvision_deeplabv3_mobilenet_v3_large 완전히 위임됨 5.7
torchvision_deeplabv3_resnet101 완전히 위임됨 35.1
torchvision_deeplabv3_resnet50 완전히 위임됨 24.5
torchvision_densenet121 완전히 위임됨 13.9
torchvision_efficientnet_b0 완전히 위임됨 3.6
torchvision_efficientnet_b1 완전히 위임됨 4.7
torchvision_efficientnet_b2 완전히 위임됨 5.0
torchvision_efficientnet_b3 완전히 위임됨 6.1
torchvision_efficientnet_b4 완전히 위임됨 7.6
torchvision_efficientnet_b5 완전히 위임됨 8.6
torchvision_efficientnet_b6 완전히 위임됨 11.2
torchvision_efficientnet_b7 완전히 위임됨 14.7
torchvision_fcn_resnet50 완전히 위임됨 19.9
torchvision_googlenet 완전히 위임됨 3.9
torchvision_inception_v3 완전히 위임됨 8.6
torchvision_lraspp_mobilenet_v3_large 완전히 위임됨 3.3
torchvision_mnasnet0_5 완전히 위임됨 2.4
torchvision_mobilenet_v2 완전히 위임됨 2.8
torchvision_mobilenet_v3_large 완전히 위임됨 2.8
torchvision_mobilenet_v3_small 완전히 위임됨 2.3
torchvision_resnet152 완전히 위임됨 15.0
torchvision_resnet18 완전히 위임됨 4.3
torchvision_resnet50 완전히 위임됨 6.9
torchvision_squeezenet1_0 완전히 위임됨 2.9
torchvision_squeezenet1_1 완전히 위임됨 2.5
torchvision_vgg16 완전히 위임됨 13.4명
torchvision_wide_resnet101_2 완전히 위임됨 25.0
torchvision_wide_resnet50_2 완전히 위임됨 13.4명
u2net_full 완전히 위임됨 98.3
u2net_lite 완전히 위임됨 51.4
hf_distil_whisper_small_no_cache 일부 위임됨 251.9
hf_distilbert 일부 위임됨 13.7
hf_tinyroberta_squad2 일부 위임됨 17.1
hf_tinyroberta_squad2_dynamic_batch 일부 위임됨 52.1
snapml_StyleTransferNet 일부 위임됨 40.9
timm_efficientformer_l1 일부 위임됨 17.6
timm_efficientformerv2_s0 일부 위임됨 16.1
timm_pvt_v2_b1 일부 위임됨 73.5
timm_pvt_v2_b3 일부 위임됨 246.7
timm_resnest14d 일부 위임됨 88.9
torchaudio_conformer 일부 위임됨 21.5
torchvision_convnext_tiny 일부 위임됨 8.2
torchvision_maxvit_t 일부 위임됨 194.0
torchvision_shufflenet_v2 일부 위임됨 9.5
torchvision_swin_tiny 일부 위임됨 164.4
torchvision_video_resnet2plus1d_18 일부 위임됨 6832.0
torchvision_video_swin3d_tiny 일부 위임됨 2617.8
yolox_tiny 일부 위임됨 11.2