# Xử lý sự cố

Hướng dẫn này cung cấp các giải pháp cho một số vấn đề bạn có thể gặp phải khi sử dụng Accelerate. Không phải tất cả các lỗi đều được đề cập vì Accelerate là một thư viện đang hoạt động tích cực, không ngừng phát triển và có rất nhiều trường hợp sử dụng cũng như các cấu hình huấn luyện phân tán khác nhau. Nếu các giải pháp được mô tả ở đây không giúp ích cho lỗi cụ thể của bạn, vui lòng xem phần [Yêu cầu hỗ trợ](#ask-for-help) để tìm hiểu nơi và cách để nhận được sự giúp đỡ.

## Ghi nhật ký

Logging có thể giúp bạn xác định nguồn gốc của một lỗi. Trong một cấu hình phân tán với nhiều tiến trình, việc ghi log có thể là một thách thức, nhưng Accelerate cung cấp tiện ích `logging()` để đảm bảo các log được đồng bộ hóa.

Để khắc phục sự cố, hãy sử dụng `logging()` thay vì module [`logging`](https://docs.python.org/3/library/logging.html#module-logging) chuẩn của Python. Đặt mức độ chi tiết (`INFO`, `DEBUG`, `WARNING`, `ERROR`, `CRITICAL`) bằng tham số `log_level`, sau đó bạn có thể:

1. Xuất `log_level` dưới dạng biến môi trường `ACCELERATE_LOG_LEVEL`.
2. Truyền `log_level` trực tiếp vào `get_logger`.

Ví dụ, để đặt `log_level="INFO"`:

```py
from accelerate.logging import get_logger

logger = get_logger(__name__, log_level="DEBUG")
```

Mặc định, log chỉ được gọi trên các tiến trình chính. Để gọi nó trên tất cả các tiến trình, hãy truyền `main_process_only=False`. Nếu log cần được gọi trên tất cả các tiến trình và theo thứ tự, hãy truyền thêm `in_order=True`.

```py
from accelerate.logging import get_logger

logger = get_logger(__name__, log_level="DEBUG")
# log all processes
logger.debug("thing_to_log", main_process_only=False)
# log all processes in order
logger.debug("thing_to_log", main_process_only=False, in_order=True)
```

## Lỗi treo mã và hết thời gian

Có thể có nhiều lý do khiến mã của bạn bị treo. Hãy cùng xem cách giải quyết một số vấn đề phổ biến nhất có thể khiến mã của bạn bị treo.

### Hình dạng tensor không khớp

Trạng thái kích thước tensor không khớp là một vấn đề phổ biến có thể khiến mã của bạn treo trong một khoảng thời gian đáng kể trên cấu hình phân tán.

Khi chạy các script trong cấu hình phân tán, các hàm như [Accelerator.gather()](/docs/accelerate/main/vi/package_reference/accelerator#accelerate.Accelerator.gather) và [Accelerator.reduce()](/docs/accelerate/main/vi/package_reference/accelerator#accelerate.Accelerator.reduce) là cần thiết để lấy các tensor từ các thiết bị khác nhau nhằm thực hiện các thao tác tập thể trên chúng. Các hàm này (và các hàm khác) dựa vào `torch.distributed` để thực hiện thao tác `gather`, điều này yêu cầu các tensor phải có **đúng cùng một shape** trên tất cả các tiến trình. Khi shape của các tensor không khớp, mã của bạn sẽ bị treo và cuối cùng sẽ gặp ngoại lệ timeout.

Bạn có thể sử dụng chế độ gỡ lỗi vận hành của Accelerate để phát hiện ngay lập tức vấn đề này. Chúng tôi khuyến nghị bật chế độ này trong quá trình thiết lập `accelerate config`, nhưng bạn cũng có thể bật nó từ CLI, dưới dạng biến môi trường, hoặc bằng cách chỉnh sửa thủ công tệp `config.yaml`.

```bash
accelerate launch --debug {my_script.py} --arg1 --arg2
```

Nếu bật chế độ gỡ lỗi bằng biến môi trường, bạn không cần gọi `accelerate launch`.

```bash
ACCELERATE_DEBUG_MODE="1" torchrun {my_script.py} --arg1 --arg2
```

Thêm `debug: true` vào tệp `config.yaml` của bạn.

```yaml
compute_environment: LOCAL_MACHINE
debug: true
```

Sau khi bạn bật chế độ gỡ lỗi, bạn sẽ nhận được một traceback chỉ ra vấn đề không khớp hình dạng tensor.

```py
Traceback (most recent call last):
  File "/home/zach_mueller_huggingface_co/test.py", line 18, in <module>
    main()
  File "/home/zach_mueller_huggingface_co/test.py", line 15, in main
    broadcast_tensor = broadcast(tensor)
  File "/home/zach_mueller_huggingface_co/accelerate/src/accelerate/utils/operations.py", line 303, in wrapper
accelerate.utils.operations.DistributedOperationException:

Cannot apply desired operation due to shape mismatches. All shapes across devices must be valid.

Operation: `accelerate.utils.operations.broadcast`
Input shapes:
  - Process 0: [1, 5]
  - Process 1: [1, 2, 5]
```

### Dừng sớm

Đối với việc dừng sớm trong huấn luyện phân tán, nếu mỗi tiến trình có một điều kiện dừng cụ thể (ví dụ: loss kiểm tra), điều kiện đó có thể không được đồng bộ hóa giữa tất cả các tiến trình. Kết quả là, lệnh break có thể xảy ra ở tiến trình 0 nhưng không xảy ra ở tiến trình 1, khiến mã của bạn treo vĩnh viễn cho đến khi xảy ra timeout.

Nếu bạn có các điều kiện dừng sớm, hãy sử dụng các phương thức `set_trigger` và `check_trigger` để đảm bảo tất cả các tiến trình kết thúc đúng cách.

```py
# Assume `should_do_breakpoint` is a custom-defined function that returns a conditional, 
# and that conditional might be true only on process 1
if should_do_breakpoint(loss):
    accelerator.set_trigger()

# Later in the training script when we need to check for the breakpoint
if accelerator.check_trigger():
    break
```

### Phiên bản kernel thấp trên Linux

Trên Linux với phiên bản kernel < 5.5, các tiến trình treo đã được báo cáo. Để tránh vấn đề này, hãy nâng cấp hệ thống của bạn lên phiên bản kernel mới hơn.

### MPI

Nếu tác vụ huấn luyện CPU phân tán của bạn sử dụng MPI bị treo, hãy đảm bảo rằng bạn đã thiết lập [SSH không mật khẩu](https://www.open-mpi.org/faq/?category=rsh#ssh-keys) (dùng khóa) giữa các nút. Điều này có nghĩa là đối với tất cả các nút trong tệp hostfile của bạn, bạn phải có thể SSH từ nút này sang nút khác mà không bị yêu cầu nhập mật khẩu.

Tiếp theo, hãy thử chạy lệnh `mpirun` để kiểm tra. Ví dụ, lệnh bên dưới nên in ra tên máy chủ (hostname) của từng node.

```bash
mpirun -f hostfile -n {number of nodes} -ppn 1 hostname
```

## Hết bộ nhớ

Một trong những lỗi gây khó chịu nhất khi chạy các script huấn luyện là gặp phải "Out-of-Memory" trên các thiết bị như CUDA, XPU hoặc CPU. Toàn bộ script cần được khởi động lại và mọi tiến độ sẽ bị mất.

Để giải quyết vấn đề này, Accelerate cung cấp tiện ích [find_executable_batch_size()](/docs/accelerate/main/vi/package_reference/utilities#accelerate.find_executable_batch_size) được xây dựng dựa nhiều vào [toma](https://github.com/BlackHC/toma). Tiện ích này sẽ chạy lại đoạn mã bị lỗi do điều kiện OOM (thiếu bộ nhớ) và tự động giảm kích thước batch. Với mỗi điều kiện OOM, thuật toán sẽ giảm kích thước batch đi một nửa và chạy lại đoạn mã cho đến khi thành công.

Để sử dụng [find_executable_batch_size()](/docs/accelerate/main/vi/package_reference/utilities#accelerate.find_executable_batch_size), hãy tái cấu trúc hàm huấn luyện của bạn để bao gồm một hàm bên trong có chứa `find_executable_batch_size` và xây dựng các dataloader bên trong hàm đó. Tối thiểu, điều này chỉ cần thêm 4 dòng code mới.

 

Hàm bên trong **phải** nhận kích thước lô (batch size) làm tham số đầu tiên, nhưng chúng ta không truyền tham số này khi gọi nó. Lớp bọc (wrapper) sẽ xử lý điều này cho bạn. Bất kỳ đối tượng nào (mô hình, bộ tối ưu hóa) tiêu tốn bộ nhớ thiết bị và được truyền vào [Accelerator](/docs/accelerate/main/vi/package_reference/accelerator#accelerate.Accelerator) cũng **phải** được khai báo bên trong hàm bên trong.

```diff
def training_function(args):
    accelerator = Accelerator()

+   @find_executable_batch_size(starting_batch_size=args.batch_size)
+   def inner_training_loop(batch_size):
+       nonlocal accelerator # Ensure they can be used in our context
+       accelerator.free_memory() # Free all lingering references
        model = get_model()
        model.to(accelerator.device)
        optimizer = get_optimizer()
        train_dataloader, eval_dataloader = get_dataloaders(accelerator, batch_size)
        lr_scheduler = get_scheduler(
            optimizer, 
            num_training_steps=len(train_dataloader)*num_epochs
        )
        model, optimizer, train_dataloader, eval_dataloader, lr_scheduler = accelerator.prepare(
            model, optimizer, train_dataloader, eval_dataloader, lr_scheduler
        )
        train(model, optimizer, train_dataloader, lr_scheduler)
        validate(model, eval_dataloader)
+   inner_training_loop()
```

## Kết quả không thể tái lập giữa các cấu hình thiết bị

Nếu bạn đã thay đổi cấu hình thiết bị và nhận thấy hiệu suất mô hình khác nhau, rất có thể bạn đã không cập nhật script khi chuyển từ cấu hình này sang cấu hình khác. Ngay cả khi bạn sử dụng cùng một script với cùng một batch size, kết quả vẫn sẽ khác nhau trên TPU, multi-GPU và single GPU.

Ví dụ, nếu bạn đang huấn luyện trên một GPU duy nhất với kích thước lô (batch size) là 16 và chuyển sang cấu hình hai GPU, bạn cần thay đổi kích thước lô thành 8 để có cùng kích thước lô hiệu dụng. Điều này là do khi huấn luyện với Accelerate, kích thước lô được truyền vào dataloader là **kích thước lô trên mỗi GPU**.

Để đảm bảo bạn có thể tái tạo kết quả giữa các cấu hình, hãy chắc chắn sử dụng cùng một seed, điều chỉnh kích thước batch cho phù hợp và xem xét việc điều chỉnh tốc độ học.

Để biết thêm chi tiết và tra cứu nhanh về kích thước lô, hãy xem hướng dẫn [So sánh hiệu suất giữa các cấu hình thiết bị khác nhau](../concept_guides/performance).

## Vấn đề hiệu năng trên các GPU khác nhau

Nếu cấu hình đa GPU của bạn bao gồm các GPU khác nhau, bạn có thể gặp một số vấn đề về hiệu suất:

- Có thể có sự mất cân bằng về bộ nhớ GPU giữa các GPU. Trong trường hợp này, GPU có bộ nhớ nhỏ hơn sẽ giới hạn kích thước lô (batch size) hoặc kích thước mô hình có thể được nạp lên các GPU.
- Nếu bạn đang sử dụng các GPU có hiệu năng khác nhau, hiệu năng tổng thể sẽ bị giới hạn bởi GPU chậm nhất mà bạn đang dùng, vì các GPU còn lại sẽ phải chờ GPU đó hoàn thành khối lượng công việc của nó.

Các GPU khác nhau đáng kể trong cùng một cấu hình có thể dẫn đến các nút thắt về hiệu suất.

## Yêu cầu hỗ trợ

Nếu không có giải pháp hay lời khuyên nào ở đây giúp giải quyết vấn đề của bạn, bạn luôn có thể liên hệ với cộng đồng và đội ngũ Accelerate để được hỗ trợ.

- Yêu cầu hỗ trợ trên diễn đàn Hugging Face bằng cách đăng câu hỏi của bạn vào [chuyên mục Accelerate](https://discuss.huggingface.co/c/accelerate/18). Hãy đảm bảo viết một bài đăng mô tả rõ ràng với ngữ cảnh liên quan về cấu hình của bạn và mã có thể tái hiện để tối đa hóa khả năng vấn đề của bạn được giải quyết!

- Đặt câu hỏi trên [Discord](http://hf.co/join/discord) và để đội ngũ cùng cộng đồng hỗ trợ bạn.

- Hãy tạo một Issue trên [kho GitHub](https://github.com/huggingface/accelerate/issues) của Accelerate nếu bạn cho rằng mình đã tìm thấy một lỗi liên quan đến thư viện. Hãy bao gồm ngữ cảnh về lỗi và các chi tiết về cấu hình phân tán của bạn để giúp chúng tôi xác định rõ hơn vấn đề và cách khắc phục.

