Accelerate documentation

Pemecahan masalah

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.15.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Pemecahan masalah

Panduan ini menyediakan solusi untuk beberapa masalah yang mungkin Anda temui saat menggunakan Accelerate. Tidak semua kesalahan tercakup karena Accelerate adalah pustaka aktif yang terus berkembang dan terdapat banyak kasus penggunaan serta konfigurasi pelatihan terdistribusi yang berbeda. Jika solusi yang dijelaskan di sini tidak membantu untuk kesalahan spesifik Anda, silakan lihat bagian Minta bantuan untuk mempelajari di mana dan bagaimana mendapatkan bantuan.

Pencatatan

Logging dapat membantu Anda mengidentifikasi asal sebuah error. Dalam setup terdistribusi dengan beberapa proses, logging bisa menjadi tantangan, tetapi Accelerate menyediakan utilitas logging() untuk memastikan log tersinkronisasi.

Untuk memecahkan masalah, gunakan logging() alih-alih modul logging Python standar. Atur tingkat detail (INFO, DEBUG, WARNING, ERROR, CRITICAL) dengan parameter log_level, lalu Anda dapat:

  1. Ekspor log_level sebagai variabel lingkungan ACCELERATE_LOG_LEVEL.
  2. Lewatkan log_level langsung ke get_logger.

Sebagai contoh, untuk mengatur log_level="INFO":

from accelerate.logging import get_logger

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

Secara default, log dipanggil hanya pada proses utama. Untuk memanggilnya pada semua proses, berikan main_process_only=False. Jika log harus dipanggil pada semua proses dan secara berurutan, berikan juga in_order=True.

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)

Kode yang menggantung dan kesalahan timeout

Ada banyak alasan mengapa kode Anda bisa macet. Mari kita lihat cara menyelesaikan beberapa masalah umum yang paling sering menyebabkan kode Anda macet.

Bentuk tensor yang tidak cocok

Bentuk tensor yang tidak cocok adalah masalah umum yang dapat menyebabkan kode Anda macet dalam waktu yang signifikan pada setup terdistribusi.

Saat menjalankan skrip dalam setup terdistribusi, fungsi seperti Accelerator.gather() dan Accelerator.reduce() diperlukan untuk mengambil tensor di berbagai perangkat guna secara kolektif melakukan operasi pada tensor tersebut. Fungsi-fungsi ini (dan fungsi lainnya) bergantung pada torch.distributed untuk melakukan operasi gather, yang mensyaratkan tensor memiliki bentuk yang persis sama di semua proses. Jika bentuk tensor tidak cocok, kode Anda akan macet dan pada akhirnya akan mencapai pengecualian timeout.

Anda dapat menggunakan mode debug operasional Accelerate untuk segera menangkap masalah ini. Kami merekomendasikan mengaktifkan mode ini selama setup accelerate config, tetapi Anda juga dapat mengaktifkannya dari CLI, sebagai variabel lingkungan, atau dengan mengedit file config.yaml secara manual.

CLI
variabel lingkungan
config.yaml
accelerate launch --debug {my_script.py} --arg1 --arg2

Setelah Anda mengaktifkan mode debug, Anda seharusnya mendapatkan traceback yang menunjukkan masalah ketidakcocokan bentuk tensor.

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]

Penghentian dini

Untuk early stopping dalam pelatihan terdistribusi, jika setiap proses memiliki kondisi penghentian tertentu (misalnya validation loss), kondisi tersebut mungkin tidak tersinkronisasi di antara semua proses. Akibatnya, break dapat terjadi pada proses 0 tetapi tidak pada proses 1, yang akan menyebabkan kode Anda menggantung tanpa batas hingga timeout terjadi.

Jika Anda memiliki kondisi early stopping, gunakan metode set_trigger dan check_trigger untuk memastikan semua proses diakhiri dengan benar.

# 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

Versi kernel yang rendah di Linux

Pada Linux dengan versi kernel < 5.5, proses yang menggantung telah dilaporkan. Untuk menghindari masalah ini, perbarui sistem Anda ke versi kernel yang lebih baru.

MPI

Jika tugas pelatihan CPU terdistribusi Anda yang menggunakan MPI mengalami hang, pastikan Anda telah mengatur SSH tanpa kata sandi (menggunakan kunci) antar node. Artinya, untuk semua node dalam hostfile Anda, Anda harus dapat SSH dari satu node ke node lain tanpa diminta memasukkan kata sandi.

Selanjutnya, coba jalankan perintah mpirun sebagai pemeriksaan kesehatan. Misalnya, perintah di bawah ini seharusnya menampilkan nama host untuk masing-masing node.

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

Kekurangan Memori

Salah satu kesalahan paling menyebalkan saat menjalankan skrip pelatihan adalah munculnya pesan “Out-of-Memory” pada perangkat seperti CUDA, XPU, atau CPU. Seluruh skrip harus dijalankan ulang dan semua kemajuan yang telah dicapai akan hilang.

Untuk mengatasi masalah ini, Accelerate menyediakan utilitas find_executable_batch_size() yang sangat bergantung pada toma. Utilitas ini mengulang kode yang gagal karena kondisi OOM (out-of-memory) dan secara otomatis menurunkan ukuran batch. Untuk setiap kondisi OOM, algoritme mengurangi ukuran batch menjadi setengahnya dan mengulang kode hingga berhasil.

Untuk menggunakan find_executable_batch_size(), susun ulang fungsi pelatihan Anda agar mencakup fungsi dalam yang berisi find_executable_batch_size dan bangun dataloader Anda di dalamnya. Secara minimal, ini hanya membutuhkan 4 baris kode baru.

Fungsi dalam harus mengambil ukuran batch sebagai parameter pertama, tetapi kami tidak melewatkan satu pun saat dipanggil. Pembungkus akan menangani ini untuk Anda. Objek apa pun (model, optimizer) yang mengonsumsi memori perangkat dan dilewatkan ke Accelerator juga harus dideklarasikan di dalam fungsi dalam.

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()

Hasil yang tidak dapat direproduksi antar konfigurasi perangkat

Jika Anda mengubah konfigurasi perangkat dan mengamati kinerja model yang berbeda, kemungkinan besar Anda tidak memperbarui skrip Anda saat berpindah dari satu konfigurasi ke konfigurasi lainnya. Bahkan jika Anda menggunakan skrip yang sama dengan ukuran batch yang sama, hasilnya tetap akan berbeda pada TPU, multi-GPU, dan GPU tunggal.

Sebagai contoh, jika Anda melatih pada satu GPU dengan ukuran batch 16 dan beralih ke setup dual GPU, Anda perlu mengubah ukuran batch menjadi 8 agar memiliki ukuran batch efektif yang sama. Hal ini terjadi karena saat melatih dengan Accelerate, ukuran batch yang diteruskan ke dataloader adalah ukuran batch per GPU.

Untuk memastikan Anda dapat mereproduksi hasil di antara berbagai konfigurasi, pastikan untuk menggunakan seed yang sama, menyesuaikan ukuran batch secara sesuai, dan mempertimbangkan penskalaan laju pembelajaran.

Untuk detail lebih lanjut dan referensi cepat mengenai ukuran batch, lihat panduan Membandingkan kinerja antara berbagai konfigurasi perangkat.

Masalah kinerja pada GPU yang berbeda

Jika konfigurasi multi-GPU Anda terdiri dari GPU yang berbeda, Anda mungkin akan mengalami beberapa masalah kinerja:

  • Mungkin terdapat ketidakseimbangan memori GPU antar GPU. Dalam kasus ini, GPU dengan memori yang lebih kecil akan membatasi ukuran batch atau ukuran model yang dapat dimuat ke GPU.
  • Jika Anda menggunakan GPU dengan profil kinerja yang berbeda, kinerja akan ditentukan oleh GPU terlama yang Anda gunakan karena GPU lainnya harus menunggu GPU tersebut menyelesaikan beban kerjanya.

GPU yang sangat berbeda dalam satu setup yang sama dapat menyebabkan bottleneck kinerja.

Minta bantuan

Jika tidak ada solusi dan saran di sini yang membantu menyelesaikan masalah Anda, Anda selalu dapat menghubungi komunitas dan tim Accelerate untuk mendapatkan bantuan.

  • Minta bantuan di forum Hugging Face dengan memposting pertanyaan Anda di kategori Accelerate. Pastikan untuk menulis postingan yang deskriptif dengan konteks yang relevan tentang setup Anda dan kode yang dapat direproduksi untuk memaksimalkan kemungkinan masalah Anda terselesaikan!

  • Ajukan pertanyaan di Discord, dan biarkan tim serta komunitas membantu Anda.

  • Buatlah Issue di repo GitHub Accelerate jika Anda merasa menemukan bug yang terkait dengan pustaka ini. Sertakan konteks mengenai bug tersebut serta detail tentang setup distribusi Anda untuk membantu kami memahami apa yang salah dan bagaimana kami dapat memperbaikinya.

Update on GitHub