그래픽 처리 장치 (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 기기에서 실행된 테스트를 기반으로 합니다.