Bộ dữ liệu phát trực tuyến- Hiệu quả hơn gấp 100 lần

  • 8 min read
Bộ dữ liệu phát trực tuyến- Hiệu quả hơn gấp 100 lần

Bộ dữ liệu Streaming: Hiệu quả hơn 100 lần

Chúng tôi đã tăng cường load_dataset('dataset', streaming=True), truyền phát bộ dữ liệu mà không cần tải xuống chỉ bằng một dòng mã!

Bắt đầu huấn luyện trên các bộ dữ liệu đa TB ngay lập tức, không cần thiết lập phức tạp, tải xuống, không có lỗi “hết dung lượng đĩa” hoặc 429 “dừng yêu cầu!”. Nó cực kỳ nhanh! Vượt xa SSD cục bộ của chúng tôi khi huấn luyện trên 64xH100 với 256 worker tải xuống dữ liệu. Chúng tôi đã cải thiện tính năng streaming để có số lượng yêu cầu ít hơn 100 lần, → độ phân giải dữ liệu nhanh hơn 10 lần → 2x mẫu/giây, → 0 worker bị crash ở 256 worker đồng thời.

Việc tải dữ liệu, đặc biệt ở quy mô terabyte, là một trở ngại lớn trong bất kỳ quy trình học máy nào. Chúng tôi đã gặp phải điều này khi huấn luyện SmolLM3, có thời điểm chúng tôi phải đợi 3 giờ trước mỗi lần chạy để tải xuống đủ dữ liệu.

Tính năng streaming luôn có sẵn trong thư viện datasets, nhưng việc huấn luyện quy mô lớn với các bộ dữ liệu khổng lồ vẫn là một thách thức. Điều đó thay đổi kể từ hôm nay 🔥. Chúng tôi đã dành vài tháng để cải thiện backend, tập trung vào việc truyền phát bộ dữ liệu để làm cho nó nhanh hơn và hiệu quả hơn.

Chúng tôi đã làm chính xác những gì? ⤵️

Streaming: API dễ dàng tương tự

Điều đầu tiên: các thay đổi của chúng tôi tương thích ngược. Bạn vẫn có thể truyền phát bất kỳ bộ dữ liệu nào từ Hub bằng cùng một flag đơn giản streaming=True. Nó dễ dàng hơn bao giờ hết. 🚀

python from datasets import load_dataset

Stream một bộ dữ liệu thay vì tải xuống

dataset = load_dataset(“HuggingFaceM4/FineVisionMax”, split=“train”, streaming=True)

Lấy ví dụ đầu tiên

print(next(iter(dataset)))

Hàng ngàn nhà phát triển AI trên khắp thế giới sử dụng datasets hàng ngày; họ sẽ chỉ nhận được hiệu suất được cải thiện mà không cần thêm bất kỳ công việc nào.

Thách thức: Streaming ở quy mô lớn

Streaming là một cứu cánh để nhanh chóng hiểu một bộ dữ liệu, nhưng để huấn luyện các mô hình, mọi người thường tải dữ liệu xuống cục bộ hoặc sử dụng dịch vụ lưu trữ đám mây như S3. Đó là những gì chúng tôi đã làm để huấn luyện SmolVLM, chúng tôi có tất cả dữ liệu của mình trên S3 và đã truyền phát trực tiếp từ đó.

Chúng tôi muốn thay đổi điều đó, vì vậy chúng tôi quyết định sử dụng tính năng streaming từ Hub khi đang phát triển nanoVLM. Chẳng mấy chốc, chúng tôi đã tìm thấy một vấn đề lớn: quá trình chạy thử nghiệm của chúng tôi đã tạo ra hơn 100.000 yêu cầu trong vòng chưa đầy một phút, điều này đã khiến IP của chúng tôi bị Hub chặn! 😅 Điều này xảy ra vì mọi worker DataLoader đều khởi tạo bộ dữ liệu một cách độc lập. Khi chúng tôi đào sâu hơn, chúng tôi thấy rằng điều này tạo ra một loạt các yêu cầu dư thừa, nhiều trong số đó là không cần thiết. Các thay đổi của chúng tôi cuối cùng đã giảm số lượng yêu cầu khởi động theo hệ số 100. Tổng cộng, những cải tiến của chúng tôi đã mang lại:

  • Thời gian phân giải tệp dữ liệu: nhanh hơn 10 lần
  • Yêu cầu khởi động: Hiệu quả hơn tới 100 lần
  • Tốc độ streaming: Nhanh hơn tới 2 lần
  • Yêu cầu đang xử lý: Hiệu quả hơn tới 2 lần

Bên dưới lớp áo: Những gì chúng tôi đã cải thiện

Vậy, những gì đã thay đổi? Chúng tôi tập trung vào hai giai đoạn: khởi động và streaming.

1. Khởi động⚡️

Việc phân giải ban đầu các tệp dữ liệu đã tạo ra rất nhiều yêu cầu. Chúng tôi đã thực hiện hai thay đổi lớn:

  • Bộ nhớ cache tệp dữ liệu liên tục: Giờ đây, chúng tôi đang lưu vào bộ nhớ cache danh sách các tệp dữ liệu trên tất cả các worker DataLoader. Worker đầu tiên phân giải danh sách tệp từ Hub. Tất cả các worker khác đọc trực tiếp từ bộ nhớ cache cục bộ này, hầu như loại bỏ các yêu cầu khởi động và giảm đáng kể thời gian phân giải. Không còn các cơn bão yêu cầu!
  • Logic phân giải được tối ưu hóa: Chúng tôi cũng giảm thiểu số lượng lệnh gọi API cần thiết để worker ban đầu đó tìm nạp danh sách tệp. Giờ đây, chúng tôi kết hợp các yêu cầu cần thiết một cách hiệu quả nhất có thể, giảm độ trễ hơn nữa.

2. Streaming 🏎️

Để cải thiện thông lượng trong quá trình streaming, chúng tôi đã giới thiệu hai tính năng mới:

  • Tìm nạp trước cho Parquet: Chúng tôi đã bật tính năng tìm nạp trước cho các bộ dữ liệu Parquet. Điều này có nghĩa là trong khi mô hình của bạn đang xử lý khối dữ liệu hiện tại, thư viện datasets đã tìm nạp khối tiếp theo trong nền. Điều này giúp cho quy trình dữ liệu luôn đầy đủ và đảm bảo GPU của bạn không bao giờ phải đợi dữ liệu.
  • Đệm có thể định cấu hình: Người dùng nâng cao giờ đây có thể tinh chỉnh hiệu suất streaming cho phần cứng và thiết lập mạng cụ thể của họ. Chúng tôi đã hiển thị các tùy chọn để định cấu hình kích thước khối của bộ đệm và khối lượng tìm nạp trước, cho phép bạn kiểm soát tối đa để tối ưu hóa I/O.

Đây là cách chúng ta có thể tăng kích thước yêu cầu tối thiểu khi truyền phát từ 32MiB (mặc định) lên 128MiB và định cấu hình tìm nạp trước:

python import pyarrow import pyarrow.dataset

fragment_scan_options = pyarrow.dataset.ParquetFragmentScanOptions( cache_options=pyarrow.CacheOptions( prefetch_limit=1, range_size_limit=128 « 20 ), ) ds = load_dataset(parquet_dataset_id, streaming=True, fragment_scan_options=fragment_scan_options)

Cùng với nhau, những cải tiến này có thể tăng gấp đôi thông lượng dữ liệu của bạn, cho phép bạn huấn luyện nhanh hơn và hiệu quả hơn.

Làm thế nào chúng tôi nhanh hơn S3 thông thường: Xet

Hugging Face sử dụng Xet: một kho lưu trữ dựa trên khử trùng lặp cho phép tải lên và tải xuống được khử trùng lặp nhanh chóng. Không giống như bộ nhớ từ xa truyền thống, việc truyền dữ liệu nhanh hơn trên Xet vì dữ liệu trùng lặp chỉ được truyền một lần. Ví dụ: việc tải lên một bộ dữ liệu quy mô lớn lên Hugging Face tận dụng Xet giúp tăng tốc độ tải lên. Sau khi bộ dữ liệu được tải lên, nó có thể được truyền phát ngay lập tức.

Khử trùng lặp cho Parquet được bật thông qua Phân đoạn được xác định nội dung (CDC) Parquet. Nhờ CDC Parquet và khử trùng lặp Xet, việc tải lên bộ dữ liệu trên Hugging Face nhanh hơn trên bất kỳ bộ nhớ từ xa truyền thống nào.

Điều này được hỗ trợ bởi gói pyspark_huggingface của chúng tôi, một Nguồn dữ liệu Spark để đọc/ghi bộ dữ liệu HF. Nó bao gồm hỗ trợ CDC Parquet và Xet, tăng tốc độ truyền dữ liệu trên HF một cách đáng kể.

Cần một quy trình streaming tùy chỉnh?

Một số định dạng tệp dữ liệu không được hỗ trợ trong datasets và đôi khi cần kiểm soát nhiều hơn, vì vậy chúng tôi đã giúp bạn dễ dàng xây dựng các quy trình streaming tùy chỉnh. Điều này đã được kiểm tra trong thư viện LeRobot để lấy mẫu các khung hình video và trong thư viện WebDataset để truyền phát kho lưu trữ TAR.

Chúng tôi đã cải thiện HfFileSystem trong thư viện huggingface_hub để đọc hiệu quả các tệp từ kho lưu trữ bộ dữ liệu Hugging Face từ xa và truyền phát dữ liệu:

python from huggingface_hub import HfFileSystem

path = f"hf://datasets/{dataset_id}/{path_in_repo}" with HfFileSystem().open(path) as f: # loop với .read() hoặc .readline() để truyền phát dữ liệu # hoặc thực hiện truy cập ngẫu nhiên với .seek()

Việc truyền một HfFileSystem tới một torch DataLoader sử dụng lại các kết quả được lưu trong bộ nhớ cache từ .ls().glob() giúp loại bỏ nhu cầu về các yêu cầu bổ sung khi liệt kê các tệp dữ liệu.

Đẩy streaming đến giới hạn

Hiện tại, chúng tôi đang sử dụng các cải tiến streaming này trong nanoVLM để huấn luyện thế hệ tiếp theo của SmolVLM. Với những chỉnh sửa này, chúng tôi đạt được hiệu suất tốt hơn từ streaming so với huấn luyện trên thiết lập đĩa cứng phân cấp của cụm của chúng tôi. Trên thực tế, streaming hiện nhanh như đọc dữ liệu từ SSD cục bộ! Trước đây, việc chuyển dữ liệu sang SSD cục bộ là quy trình thường trì hoãn quá trình huấn luyện của chúng tôi ba giờ. Để biết thêm chi tiết, hãy xem GitHub của chúng tôi.

Bắt đầu và xem sự khác biệt

Các tính năng mới mạnh mẽ này đã được đưa vào thư viện datasets và huggingface_hub. Để tận dụng chúng, chỉ cần cập nhật thư viện của bạn và xem tài liệu:

bash pip install –upgrade datasets huggingface_hub

Để ăn mừng điều này, chúng tôi đã ghép nối trước và xáo trộn tất cả các nguồn dữ liệu trong FineVision thành FineVisionMax. Bạn có thể sử dụng bộ dữ liệu kết hợp duy nhất này để huấn luyện VLM của mình - không cần phải xử lý nhiều bộ dữ liệu theo cách thủ công!

python from datasets import load_dataset

Stream một bộ dữ liệu thay vì tải xuống

dataset = load_dataset(“HuggingFaceM4/FineVisionMax”, split=“train”, streaming=True)

Lấy ví dụ đầu tiên

print(next(iter(dataset)))

Và bạn có thể xem cách chúng tôi thực hiện nó ở quy mô lớn trong nanoVLM!

Chúc bạn streaming vui vẻ! 🤗

Recommended for You

LeRobot v0.4.0- Siêu nạp cho học tập Robotics OSS

LeRobot v0.4.0- Siêu nạp cho học tập Robotics OSS

LeRobot v0.4.0 nhằm mục đích đơn giản hóa hơn nữa các thí nghiệm nghiên cứu trong lĩnh vực học tập robot nguồn mở.

Trung tâm Hugging Face v1.0- Năm năm xây dựng nền tảng của Máy học Mở

Trung tâm Hugging Face v1.0- Năm năm xây dựng nền tảng của Máy học Mở

Bản phát hành lớn này đánh dấu một cột mốc quan trọng trong quá trình phát triển trung tâm, bao gồm các khả năng của nó và những gì mong đợi trong tương lai.