+2

NVIDIA DALI - Tăng tốc xử lý dữ liệu ?

Introduction

Khi huấn luyện các mô hình deep learning, chúng ta thường dành nhiều sự quan tâm đến kiến trúc mô hình, lựa chọn loss function phù hợp, optimizer, tuning hyperparameters,... Nhưng có một thứ cũng khá quan trọng mà ta thường không quan tâm nhiều đó là hiệu suất xử lý dữ liệu đầu vào.

Multi-stage data preprocessing pipelines bao gồm loading, decoding hay augmentations là bước không thể thiếu trong các ứng dụng liên quan đến học sâu, các pipelines này hiện đang được xử lý trên CPU đã trở thành bottleneck cản trở hiệu suất và khả năng scalability của quá trình training và inference khi mà mô hình thì chờ dữ liệu, còn CPU thì trì trệ để xử lý ảnh từng batch một. Bởi vậy mà ta có thể tham khảo một thư viện cho data preprocessing, NVIDIA DALI (Data Loading Library) ra đời để giải quyết vấn đề này.

Overview

NVIDIA Data Loading Library (DALI) là một thư viện GPU-accelerated cho data loadingdata preprocessing để tăng tốc các ứng dụng học sâu. Thư viện cung cấp các building blocks được tối ưu hóa cao để tải và xử lý dữ liệu hình ảnh, video và âm thanh. Nó có thể được sử dụng như một sự thay thế cho data loaders và data iterators trong các deep learning frameworks.

Ngoài ra, deep learning frameworks có nhiều triển khai tiền xử lý dữ liệu, dẫn đến những thách thức như tính di động của quy trình training và inference, và khả năng bảo trì code. Data processing pipelines được triển khai bằng DALI có tính di động vì chúng có thể dễ dàng được chuyển hướng sang TensorFlow, PyTorch, ...

Dưới đây là hình ảnh minh họa trong thực tiễn, nhìn phát là hiểu:

image.png

Highlights

Dưới đây là một số điểm chính mà documentations của DALI có đề cập:

  • API Python theo phong cách chức năng dễ sử dụng.
  • Hỗ trợ nhiều định dạng dữ liệu - LMDB, RecordIO, TFRecord, COCO, JPEG, JPEG 2000, WAV, FLAC, OGG, H.264, VP9 và HEVC.
  • Hỗ trợ deep learning frameworks: TensorFlow, PyTorch, PaddlePaddle, JAX.
  • Hỗ trợ thực thi CPU và GPU, multi-GPU
  • Customize pipelines, operators, ...
  • Tăng tốc image classification (ResNet-50), object detecttion (SSD) workloads cũng như các mô hình ASR (Jasper, RNN-T).
  • Cho phép đường dẫn dữ liệu trực tiếp giữa sotrage và GPU memory với GPUDirect Storage.
  • Dễ dàng tích hợp với NVIDIA Triton Inference Server với DALI TRITON Backend.
  • Quan trọng và không thể thiếu: Open-source

Ngoài ra, DALI hỗ trợ toàn bộ tất cả Linux distribution và gián tiếp với Windows thông qua WSL, tuy nhiên MacOS thì chưa.

Một số thông tin cơ bản

Data pipeline

Trong DALI, các tác vụ xử lý dữ liệu thông qua Pipeline. Đây là một instance của nvidia.dali.Pipeline hoặc derived class. Pipeline đóng gói data preprocessing graph và execution engine. Một số cách định nghĩa DALI pipeline:

  • Sử dụng decorator pipeline_def() cho một function.

  • Khởi tạo trực tiếp đối tượng Pipeline, xây dựng graph và thiết lập đầu ra của pipeline với Pipeline.set_outputs().

  • Kế thừa từ Pipeline class và override Pipeline.define_graph().

Data Processing Graphs

DALI pipeline được biểu diến như đồ thị operatorations, bao gồm 2 loại nodes trong graph:

  • Operators
  • DataNode: inputs và outputs của operators Datanode có thể được transformed bằng cách gọi các hàm operator. Chúng cũng hỗ trợ Python-style indexing và có thể được kết hợp trong các biểu thức toán học.

Ví dụ:

@pipeline_def  # create a pipeline with processing graph
def my_pipeline():
    """ Create a pipeline which reads images and masks, decodes the images and
        returns them. """
    img_files, labels = fn.readers.file(file_root="image_dir", device='cpu')
    mask_files, _ = fn.readers.file(file_root="mask_dir", seed=1)
    images = fn.decoders.image(img_files, device="mixed")
    masks  = fn.decoders.image(mask_files, device="mixed")
    return images, masks, labels

pipe = my_pipeline(batch_size=4, num_threads=2, device_id=0)

Đồ thị có dạng: Screenshot from 2025-05-24 23-26-14.png

Data pipelines được thực thi trong các stages và sẽ tương ứng với tham số device được xác định trong operator và thực thi theo thứ tự sau:

  • cpu: operators chấp nhận CPU inputs và tạo CPU outputs
  • mixed: CPU inputs và GPU outputs
  • gpu: GPU inputs và outputs

Conditional Execution:

Như cái tên, DALI cũng cho phép thực thi operators conditional với if: DALI cho phép thực thi các toán tử có điều kiện cho samples trong batch bằng cách sử dụng các câu lệnh if. Để sử dụng, ta cần set @pipeline_def và đặt enable_conditionals=True. Mỗi câu lệnh if có DataNode() làm điều kiện sẽ được nhận dạng là câu lệnh có điều kiện DALI. Trong ví dụ dưới đây, pipelines xoay từng hình ảnh với xác suất 25% theo một góc ngẫu nhiên từ 10 đến 20 độ:

@pipeline_def(num_threads=4, device_id=0, enable_conditionals=True)
def get_dali_pipeline():
    images, labels = fn.readers.file(
        file_list="ship/file_list.txt", random_shuffle=True, name="Reader")
    # decode data on the GPU
    images = fn.decoders.image_random_crop(
        images, device="mixed", output_type=types.RGB)
    images = fn.resize(images, resize_x=256, resize_y=256)
    images = fn.crop_mirror_normalize(
        images,
        output_layout="HWC",
        crop_h=224,
        crop_w=224,
        mean=[0.485 * 255, 0.456 * 255, 0.406 * 255],
        std=[0.229 * 255, 0.224 * 255, 0.225 * 255],
        mirror=fn.random.coin_flip())
    
    do_rotate = fn.random.coin_flip(probability=0.25, dtype=types.DALIDataType.BOOL)
    if do_rotate:
        images = fn.rotate(images, angle=fn.random.uniform(range=(10, 20)), fill_value=0, keep_size=True)
        
    return images, labels

Bạn có thể thử chạy pipeline trên với enable_conditionals=False, code chắc chắn sẽ lỗi như sau TypeError: "DataNode" was used in conditional context - it might have been used in truth evaluation forifstatement.

Điều kiện phải được biểu diễn bằng các mẫu vô hướng - tức là có dạng 0-d. Nó có thể là boolean hoặc bất kỳ kiểu số nào được DALI hỗ trợ, các giá trị khác 0 được coi là True và các giá trị bằng 0 được coi là False.

Ngoài ra, các biểu thức logic and, or, và not có thể được sử dụng trên DataNode(). Hai biểu thức đầu tiên bị giới hạn ở các đầu vào boolean, not cho phép các kiểu đầu vào giống như câu lệnh if condition. Biểu thức logic tuân theo các quy tắc tắt khi chúng được đánh giá.

Indexing and Slicing

Trong DALI, các DataNode cũng có thể indexed vaf sliced sử dụng Python syntax dạng array indexing như kiểu a[indexed] tron đó a là DALI DataNode và indexed là con số selection, selection cũng có thể là index hoặc slice.

Ví dụ:

images = fn.decoders.image(...)
sizes = fn.sizes(images)  # height, width, channels

height = sizes[0]
width  = sizes[1]

# Hay indexed từ cuối
channels = sizes[-1]   # channels go last
widths = sizes[-2]     # widths are the innermost dimension after channels

Còn với Slicing thì cũng tương tự như thao tác với mảng thôi:

header = raw_files[:16]  # extract 16-byte headers from files in the batch

# Multi dimensional selection
images = fn.decoders.image(jpegs, device="mixed")  # RGB images in HWC layout
red =   images[:,:,0]
green = images[:,:,1]
blue =  images[:,:,2]

Operation Reference

Data processing graph trong DALI Pipeline được xác định bằng cách gọi các operation functions. Chúng chấp nhận và trả về các instances của DataNode, là các biểu diễn của cấc batch Tensor. Các hoperation functions không thể được sử dụng để xử lý dữ liệu trực tiếp.

DALI hỗ trợ rất nhiều các operations bao gồm cả việc đọc, xử lý dữ liệu audio, video và phổ biến nhất là image. Các bạn có thể tham khảo bảng tổng hợp toàn bộ operation functions ở đây chứ mình không thể nào liệt kê hết được :v . Tùy vào mục đích sử dụng của các bạn. Operation References

Types and Mathematical Expressions

DALI cũng hỗ trợ rất nhiều kiểu loại dữ liệu và các hàm toán học, phép toán số học bao gồm cách thức cũng như cách nó hoạt động, mọi người có thể tham khảo thêm trong tài liệu của DALI.

Automatic Augmentations

Automatic augmentations là các probabilistic augmentation policies. Khi sử dụng, mỗi mẫu dữ liệu được xử lý bằng các phép tăng cường (các thao tác biến đổi hình ảnh) được chọn ngẫu nhiên theo một số phân phối xác suất được xác định. DALI triển khai các phép tăng cường tự động bằng cách sử dụng thực thi có điều kiện.

Module nvidia.dali.auto_aug đã hỗ trợ 1 số phép tăng cường bao gồm: AutoAugment, RandAugment và TrivialAugment để dùng trực tiếp trong pipelines. Ta cũng có thể customize hoặc xác định các cách mới.

Để sử dụng , ta cần xác định pipeline sử dụng decorator @pipeline_def và đặt enable_conditionals=True. Tiếp theo, gọi automatic augmentation trong pipeline. Ví dụ nếu ta muốn sử dụng AutoAugment cho bộ dữ liệu Imagenet chẳng hạn:

from nvidia.dali import pipeline_def, fn, types
from nvidia.dali.auto_aug import auto_augment


@pipeline_def(enable_conditionals=True)
def training_pipe(data_dir, image_size):

    jpegs, labels = fn.readers.file(file_root=data_dir, ...)
    shapes = fn.peek_image_shape(jpegs)
    images = fn.decoders.image(jpegs, device="mixed", output_type=types.RGB)

    # Applies the AutoAugment policy for ImageNet
    augmented_images = auto_augment.auto_augment_image_net(images, shape=shapes)

    resized_images = fn.resize(augmented_images, size=[image_size, image_size])

    return resized_images, labels

Một số khái niệm trong Automatic Augmentations:

  • augmentation: Danh sách các phép tăng cường được sử dụng trong AutoAugment, RandAugment và TrivialAugment, cũng như API để tùy chỉnh. Có thể sử dụng decorator @augmentation để triển khai các phép tăng cường mới.

  • policy - tập hợp các phép tăng cường và tham số mô tả cách áp dụng cho input cũng như "mức độ" của hoạt động.

  • apply operation - hàm gọi policy đã chỉ định trên một loạt hình ảnh trong DALI pipeline.

Tổng kết

Bài viết này của mình chỉ cho mục đích giới thiệu thông tin cơ bản cũng như mục đích của DALI thôi. Nếu các bạn muốn đọc thêm về DALI advanced thì mọi người nên đọc trực tiếp từ trong tài liệu cho đầy đủ. Chắc bài viết này ngắn gọn vậy thôi, trong bài viết tới mình sẽ thử trải nghiệm hiệu suất của DALi xem như thế nào nhé. Nếu có thời gian mình cũng sẽ thử dùng cả DALI cho inference với Triton Inference Server với DALi Backend.

Reference


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.