Avatar
Ba
Làm việc với hàng tỷ điểm dữ liệu như thế nào?
Attachments

Làm việc với dữ liệu văn bản lớn


Nếu bạn cần phải làm việc 20GB dữ liệu văn bản mà máy tính của bạn chỉ có 4B RAM, chuyện gì sẽ xảy ra nếu bạn sử dụng trực tiếp Python để load file này? Câu trả lời rất đơn giản, máy tính của các bạn sẽ bị tràn RAM.

Một ví dụ về bộ dataset cỡ lớn: PILE, bộ dữ liệu này có 15518009 dòng, rất lớn đúng không?

Vậy giải quyết vấn đề này như thế nào?

Cùng làm quen với khái niệm Memory-mapped file.

Memory Mapping là cơ chế ánh xạ (map) một phần của file hoặc toàn bộ file trên ổ cứng (disk) thành một đoạn trên bộ nhớ. Việc này cho phép chúng ta có thể truy cập vào từng phần của một file lớn như trên thay vì phải load toàn bộ file lên RAM khiến tràn RAM.

1) Thực hành trải nghiệm Memory Mapped Files với pyarrow nhé.

Ví dụ bạn ghi dữ liệu ra một file

with pa.OSFile('example3.dat', 'wb') as f:
    f.write(b'some example data')

Sau đó bạn tiến hành đọc file này:

mmap = pa.memory_map('example3.dat')
mmap.read(4)

Bạn đã đọc một phần của file có nội dung:

b'some'

Với cách đọc từ memory map ở bên trên, thư viện sẽ đọc từng phần của file đã được ánh xạ trên RAM.

Nếu in tất cả ra thì các bạn thấy file đã được chia thành nhiều phần:

for i in range(1, 7):
    print(mmap.read(i))

Kết quả hiện ra

b's'
b'om'
b'e e'
b'xamp'
b'le da'
b'ta'

Rõ ràng trong AI cách thức này rất có lợi. Ví dụ khi bạn sử dụng Batch Gradient Descent, bạn sẽ không cần đọc toàn bộ dữ liệu một lúc, thay vào đó ta sẽ load từng phần, xử lý và training.

2) Ứng dụng trong các thư viện AI

Giả sử bạn tải một file dataset từ HuggingFace - Đây chính là một thư viện ứng dụng mạnh mẽ khái niệm bên trên. Xem thêm thư viện này.

from datasets import load_dataset

# This takes a few minutes to run, so go grab a tea or coffee while you wait :)
data_files = "https://the-eye.eu/public/AI/pile_preliminary_components/PUBMED_title_abstracts_2019_baseline.jsonl.zst"
pubmed_dataset = load_dataset("json", data_files=data_files, split="train")

File này dung lượng 19.54GB

print(f"Number of files in dataset : {pubmed_dataset.dataset_size}")
size_gb = pubmed_dataset.dataset_size / (1024**3)
print(f"Dataset size (cache file) : {size_gb:.2f} GB")
Number of files in dataset : 20979437051
Dataset size (cache file) : 19.54 GB

Sau đó bạn sử dụng thư viện psutil để kiểm tra xem biến pubmed_dataset thực sự đang chiếm bao nhiêu không gian trên RAM?

import psutil

# Process.memory_info is expressed in bytes, so convert to megabytes
print(f"RAM used: {psutil.Process().memory_info().rss / (1024 * 1024):.2f} MB")
RAM used: 5678.33 MB

Chỉ khoảng hơn 5GB được sử dụng bao gồm cả Python và các biến môi trường khác nên độ lớn biến của chúng ta nhỏ hơn con số này.

Rõ ràng ta nhận ra biến này đại diện cho việc mapping đã được nhắc ở bên trên, luôn luôn load một phần của file.