Đơn vị xử lý đồ hoạ (GPU) thường được dùng để tăng tốc học sâu do có băng thông song song khổng lồ so với CPU. LiteRT Next đơn giản hoá quy trình sử dụng tính năng tăng tốc GPU bằng cách cho phép người dùng chỉ định tính năng tăng tốc phần cứng làm tham số khi tạo Mô hình đã biên dịch (CompiledModel
). LiteRT Next cũng sử dụng phương thức triển khai tăng tốc GPU mới và cải tiến mà LiteRT không cung cấp.
Với tính năng tăng tốc GPU của LiteRT Next, bạn có thể tạo vùng đệm đầu vào và đầu ra phù hợp với GPU, đạt được tính năng không sao chép với dữ liệu trong bộ nhớ GPU và thực thi các tác vụ không đồng bộ để tối đa hoá tính song song.
Để biết ví dụ về cách triển khai LiteRT Next có hỗ trợ GPU, hãy tham khảo các ứng dụng minh hoạ sau:
Thêm phần phụ thuộc GPU
Hãy làm theo các bước sau để thêm phần phụ thuộc GPU vào ứng dụng Kotlin hoặc C++.
Kotlin
Đối với người dùng Kotlin, trình tăng tốc GPU được tích hợp sẵn và không yêu cầu thêm bước nào ngoài hướng dẫn Bắt đầu.
C++
Đối với người dùng C++, bạn phải tạo các phần phụ thuộc của ứng dụng bằng tính năng tăng tốc GPU LiteRT. Quy tắc cc_binary
đóng gói logic ứng dụng cốt lõi (ví dụ: main.cc
) yêu cầu các thành phần thời gian chạy sau:
- Thư viện dùng chung API LiteRT C: thuộc tính
data
phải bao gồm thư viện dùng chung API LiteRT C (//litert/c:litert_runtime_c_api_shared_lib
) và các thành phần dành riêng cho GPU (@litert_gpu//:jni/arm64-v8a/libLiteRtGpuAccelerator.so
). - Phần phụ thuộc thuộc tính: Thuộc tính
deps
thường bao gồm các phần phụ thuộc GLESgles_deps()
vàlinkopts
thường bao gồmgles_linkopts()
. Cả hai đều có liên quan chặt chẽ đến tính năng tăng tốc GPU, vì LiteRT thường sử dụng OpenGLES trên Android. - Tệp mô hình và các thành phần khác: Được đưa vào thông qua thuộc tính
data
.
Sau đây là ví dụ về quy tắc 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
)
Chế độ thiết lập này cho phép tệp nhị phân đã biên dịch của bạn tải và sử dụng GPU một cách linh động để tăng tốc suy luận học máy.
Bắt đầu
Để bắt đầu sử dụng trình tăng tốc GPU, hãy truyền tham số GPU khi tạo Mô hình đã biên dịch (CompiledModel
). Đoạn mã sau đây cho thấy cách triển khai cơ bản của toàn bộ quy trình:
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()
Để biết thêm thông tin, hãy xem hướng dẫn Bắt đầu với C++ hoặc Bắt đầu với Kotlin.
Trình tăng tốc GPU LiteRT Next
Trình tăng tốc GPU mới (chỉ có trong LiteRT Next) được tối ưu hoá để xử lý khối lượng công việc AI, chẳng hạn như phép nhân ma trận lớn và bộ nhớ đệm KV cho LLM, hiệu quả hơn so với các phiên bản trước. Trình tăng tốc GPU LiteRT Next có các điểm cải tiến chính sau đây so với phiên bản LiteRT:
- Mở rộng phạm vi hoạt động của toán tử: Xử lý các mạng nơron lớn hơn và phức tạp hơn.
- Khả năng tương tác tốt hơn của bộ đệm: Cho phép sử dụng trực tiếp bộ đệm GPU cho khung máy ảnh, hoạ tiết 2D hoặc trạng thái LLM lớn.
- Hỗ trợ thực thi không đồng bộ: Lồng ghép quá trình xử lý trước của CPU với suy luận GPU.
Không sao chép với tính năng tăng tốc GPU
Việc sử dụng tính năng không sao chép cho phép GPU truy cập trực tiếp vào dữ liệu trong bộ nhớ của chính GPU mà không cần CPU sao chép dữ liệu đó một cách rõ ràng. Bằng cách không sao chép dữ liệu vào và từ bộ nhớ CPU, tính năng không sao chép có thể làm giảm đáng kể độ trễ toàn bộ.
Mã sau đây là ví dụ về cách triển khai GPU không sao chép bằng OpenGL, một API để kết xuất đồ hoạ vectơ. Mã này truyền hình ảnh ở định dạng vùng đệm OpenGL trực tiếp đến 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());
Thực thi không đồng bộ
Các phương thức không đồng bộ của LiteRT, chẳng hạn như RunAsync()
, cho phép bạn lên lịch dự đoán GPU trong khi tiếp tục các tác vụ khác bằng CPU hoặc NPU. Trong các quy trình phức tạp, GPU thường được sử dụng không đồng bộ cùng với CPU hoặc NPU.
Đoạn mã sau đây dựa trên mã được cung cấp trong ví dụ về Tăng tốc GPU không sao chép. Mã này sử dụng cả CPU và GPU một cách không đồng bộ và đính kèm Event
LiteRT vào vùng đệm đầu vào. LiteRT Event
chịu trách nhiệm quản lý nhiều loại nguyên hàm đồng bộ hoá và mã sau đây sẽ tạo một đối tượng LiteRT Event được quản lý thuộc loại LiteRtEventTypeEglSyncFence
. Đối tượng Event
này đảm bảo rằng chúng ta không đọc từ vùng đệm đầu vào cho đến khi GPU hoàn tất. Tất cả việc này được thực hiện mà không cần đến 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));
Mô hình được hỗ trợ
LiteRT Next hỗ trợ tính năng tăng tốc GPU với các mô hình sau. Kết quả đo điểm chuẩn dựa trên các thử nghiệm chạy trên thiết bị Samsung Galaxy S24.
Mô hình | Tăng tốc GPU LiteRT | GPU LiteRT (ms) |
---|---|---|
hf_mms_300m | Được uỷ quyền đầy đủ | 19,6 |
hf_mobilevit_small | Được uỷ quyền đầy đủ | 8.7 |
hf_mobilevit_small_e2e | Được uỷ quyền đầy đủ | 8.0 |
hf_wav2vec2_base_960h | Được uỷ quyền đầy đủ | 9.1 |
hf_wav2vec2_base_960h_dynamic | Được uỷ quyền đầy đủ | 9,8 |
isnet | Được uỷ quyền đầy đủ | 43,1 |
timm_efficientnet | Được uỷ quyền đầy đủ | 3.7 |
timm_nfnet | Được uỷ quyền đầy đủ | 9.7 |
timm_regnety_120 | Được uỷ quyền đầy đủ | 12.1 |
torchaudio_deepspeech | Được uỷ quyền đầy đủ | 4,6 |
torchaudio_wav2letter | Được uỷ quyền đầy đủ | 4.8 |
torchvision_alexnet | Được uỷ quyền đầy đủ | 3.3 |
torchvision_deeplabv3_mobilenet_v3_large | Được uỷ quyền đầy đủ | 5.7 |
torchvision_deeplabv3_resnet101 | Được uỷ quyền đầy đủ | 35.1 |
torchvision_deeplabv3_resnet50 | Được uỷ quyền đầy đủ | 24,5 |
torchvision_densenet121 | Được uỷ quyền đầy đủ | 13,9 |
torchvision_efficientnet_b0 | Được uỷ quyền đầy đủ | 3.6 |
torchvision_efficientnet_b1 | Được uỷ quyền đầy đủ | 4,7 |
torchvision_efficientnet_b2 | Được uỷ quyền đầy đủ | 5 |
torchvision_efficientnet_b3 | Được uỷ quyền đầy đủ | 6.1 |
torchvision_efficientnet_b4 | Được uỷ quyền đầy đủ | 7.6 |
torchvision_efficientnet_b5 | Được uỷ quyền đầy đủ | 8.6 |
torchvision_efficientnet_b6 | Được uỷ quyền đầy đủ | 11.2 |
torchvision_efficientnet_b7 | Được uỷ quyền đầy đủ | 14,7 |
torchvision_fcn_resnet50 | Được uỷ quyền đầy đủ | 19,9 |
torchvision_googlenet | Được uỷ quyền đầy đủ | 3,9 |
torchvision_inception_v3 | Được uỷ quyền đầy đủ | 8.6 |
torchvision_lraspp_mobilenet_v3_large | Được uỷ quyền đầy đủ | 3.3 |
torchvision_mnasnet0_5 | Được uỷ quyền đầy đủ | 2.4 |
torchvision_mobilenet_v2 | Được uỷ quyền đầy đủ | 2.8 |
torchvision_mobilenet_v3_large | Được uỷ quyền đầy đủ | 2.8 |
torchvision_mobilenet_v3_small | Được uỷ quyền đầy đủ | 2.3 |
torchvision_resnet152 | Được uỷ quyền đầy đủ | 15 |
torchvision_resnet18 | Được uỷ quyền đầy đủ | 4,3 |
torchvision_resnet50 | Được uỷ quyền đầy đủ | 6,9 |
torchvision_squeezenet1_0 | Được uỷ quyền đầy đủ | 2.9 |
torchvision_squeezenet1_1 | Được uỷ quyền đầy đủ | 2.5 |
torchvision_vgg16 | Được uỷ quyền đầy đủ | 13,4 |
torchvision_wide_resnet101_2 | Được uỷ quyền đầy đủ | 25,0 |
torchvision_wide_resnet50_2 | Được uỷ quyền đầy đủ | 13,4 |
u2net_full | Được uỷ quyền đầy đủ | 98,3 |
u2net_lite | Được uỷ quyền đầy đủ | 51,4 |
hf_distil_whisper_small_no_cache | Đã uỷ quyền một phần | 251,9 |
hf_distilbert | Đã uỷ quyền một phần | 13,7 |
hf_tinyroberta_squad2 | Đã uỷ quyền một phần | 17.1 |
hf_tinyroberta_squad2_dynamic_batch | Đã uỷ quyền một phần | 52,1 |
snapml_StyleTransferNet | Đã uỷ quyền một phần | 40,9 |
timm_efficientformer_l1 | Đã uỷ quyền một phần | 17,6 |
timm_efficientformerv2_s0 | Đã uỷ quyền một phần | 16.1 |
timm_pvt_v2_b1 | Đã uỷ quyền một phần | 73,5 |
timm_pvt_v2_b3 | Đã uỷ quyền một phần | 246,7 |
timm_resnest14d | Đã uỷ quyền một phần | 88,9 |
torchaudio_conformer | Đã uỷ quyền một phần | 21,5 |
torchvision_convnext_tiny | Đã uỷ quyền một phần | 8.2 |
torchvision_maxvit_t | Đã uỷ quyền một phần | 194,0 |
torchvision_shufflenet_v2 | Đã uỷ quyền một phần | 9.5 |
torchvision_swin_tiny | Đã uỷ quyền một phần | 164,4 |
torchvision_video_resnet2plus1d_18 | Đã uỷ quyền một phần | 6832 |
torchvision_video_swin3d_tiny | Đã uỷ quyền một phần | 2.617,8 |
yolox_tiny | Đã uỷ quyền một phần | 11.2 |