[ad_1]
Thực tiễn tốt nhất về Torch.multiprocessing
Tuy nhiên, bộ nhớ ảo chỉ là một mặt của câu chuyện. Điều gì sẽ xảy ra nếu sự cố không biến mất sau khi điều chỉnh đĩa hoán đổi?
Mặt khác của câu chuyện là các vấn đề cơ bản của mô-đun torch.multiprocessing. Có một số khuyến nghị về phương pháp hay nhất trên trang net chính thức:
Nhưng bên cạnh đó, cần xem xét thêm ba cách tiếp cận khác, đặc biệt là liên quan đến việc sử dụng bộ nhớ.
Điều đầu tiên là rò rỉ bộ nhớ chia sẻ. Rò rỉ có nghĩa là bộ nhớ không được giải phóng đúng cách sau mỗi lần chạy của kernel con và bạn sẽ quan sát thấy hiện tượng này khi theo dõi việc sử dụng bộ nhớ ảo trong thời gian chạy. Mức tiêu thụ bộ nhớ sẽ tiếp tục tăng và đạt đến mức “hết bộ nhớ”. Đây là một rò rỉ bộ nhớ rất điển hình.
Vậy nguyên nhân gây rò rỉ là gì?
Chúng ta hãy xem chính lớp DataLoader:
https://github.com/pytorch/pytorch/blob/main/torch/utils/data/dataloader.py
Nhìn sâu hơn vào DataLoader, chúng ta sẽ thấy rằng khi nums_worker > 0, _MultiProcessingDataLoaderIter được gọi. Bên trong _MultiProcessingDataLoaderIter, Torch.multiprocessing tạo hàng đợi công nhân. Torch.multiprocessing sử dụng hai chiến lược khác nhau để chia sẻ bộ nhớ và lưu vào bộ nhớ đệm: file_descriptor Và hệ thống tập tin. Trong khi hệ thống tập tin không yêu cầu bộ đệm mô tả tập tin, nó dễ bị rò rỉ bộ nhớ dùng chung.
Để kiểm tra xem máy của bạn đang sử dụng chiến lược chia sẻ nào, chỉ cần thêm vào tập lệnh:
torch.multiprocessing.get_sharing_strategy()
Để nhận giới hạn mô tả tệp hệ thống (Linux), hãy chạy lệnh sau trong thiết bị đầu cuối:
ulimit -n
Để chuyển chiến lược chia sẻ của bạn sang file_descriptor:
torch.multiprocessing.set_sharing_strategy(‘file_descriptor’)
Để đếm số lượng bộ mô tả tệp đã mở, hãy chạy lệnh sau:
ls /proc/self/fd | wc -l
Chỉ cần hệ thống cho phép, file_descriptor chiến lược được khuyến khích.
Thứ hai là phương pháp bắt đầu công nhân đa xử lý. Nói một cách đơn giản, đó là cuộc tranh luận về việc nên sử dụng fork hay sinh sản làm phương pháp bắt đầu công nhân. Fork là cách mặc định để bắt đầu đa xử lý trong Linux và có thể tránh sao chép một số tệp nhất định, do đó, cách này nhanh hơn nhiều nhưng có thể gặp sự cố khi xử lý các tensor CUDA và thư viện bên thứ ba như OpenCV trong DataLoader của bạn.
Để sử dụng phương thức spawn, bạn chỉ cần truyền đối số đa xử lý_context= “đẻ trứng”. tới Trình tải dữ liệu.
Ba, làm cho các đối tượng tập dữ liệu có thể chọn/có thể tuần tự hóa
Có một bài đăng cực hay thảo luận thêm về hiệu ứng “sao chép khi đọc” đối với quá trình gấp: https://ppwwyyxx.com/blog/2022/Demystify-RAM-Usage-in-Multiprocess-DataLoader/
Nói một cách đơn giản, đó là không còn là một cách tiếp cận tốt để tạo danh sách tên tệp và tải chúng theo phương thức __getitem__. Tạo một mảng gọn gàng hoặc khung dữ liệu gấu trúc để lưu trữ danh sách tên tệp cho mục đích tuần tự hóa. Và nếu bạn đã quen với HuggingFace thì việc sử dụng CSV/khung dữ liệu là cách được khuyên dùng để tải tập dữ liệu cục bộ: https://huggingface.co/docs/datasets/v2.19.0/en/package_reference/loading_methods#datasets.load_dataset.example-2
[ad_2]
Source link