# Hata Ayıklama

Dağıtık eğitim sorunlarını hata ayıklama genellikle şu kategorilerden birine girer: sayısal sorunlar, iletişim hataları, çalışma zamanı hataları ve derleme hataları.

## Underflow ve overflow algılama

Underflow ve overflow, aktivasyonlar veya ağırlıklar `inf` ya da `nan` değerlerine ulaştığında veya `loss=NaN` olduğunda meydana gelir. Bunları tespit etmek için `TrainingArguments.debug()` içinde `DebugUnderflowOverflow` modülünü etkinleştirin veya modülü içe aktarıp kendi eğitim döngünüze ekleyin.

```py
from transformers import TrainingArguments

args = TrainingArguments(
    debug="underflow_overflow",
    ...
)
```

```py
from transformers.debug_utils import DebugUnderflowOverflow

debug_overflow = DebugUnderflowOverflow(model)
```

[DebugUnderflowOverflow](/docs/transformers/v5.23.0/tr/internal/trainer_utils#transformers.debug_utils.DebugUnderflowOverflow), her ileri çağrıdan sonra girdi ve çıktı değişkenlerini ile bunlara karşılık gelen model ağırlıklarını test etmek için modele kancalar yerleştirir. Aktivasyonlarda veya ağırlıklarda en az bir öğede `inf` veya `nan` algılandığında, modül aşağıdaki gibi bir rapor basar.

Aşağıdaki örnek, [google/mt5-small](https://huggingface.co/google/mt5-small) ile fp16 karma hassasiyetli eğitim içindir.

```shell
Detected inf/nan during batch_number=0
Last 21 forward frames:
abs min  abs max  metadata
                  encoder.block.1.layer.1.DenseReluDense.dropout Dropout
0.00e+00 2.57e+02 input[0]
0.00e+00 2.85e+02 output
[...]
                  encoder.block.2.layer.0 T5LayerSelfAttention
6.78e-04 3.15e+03 input[0]
2.65e-04 3.42e+03 output[0]
             None output[1]
2.25e-01 1.00e+04 output[2]
                  encoder.block.2.layer.1.layer_norm T5LayerNorm
8.69e-02 4.18e-01 weight
2.65e-04 3.42e+03 input[0]
1.79e-06 4.65e+00 output
                  encoder.block.2.layer.1.DenseReluDense.wi_0 Linear
2.17e-07 4.50e+00 weight
1.79e-06 4.65e+00 input[0]
2.68e-06 3.70e+01 output
                  encoder.block.2.layer.1.DenseReluDense.wi_1 Linear
8.08e-07 2.66e+01 weight
1.79e-06 4.65e+00 input[0]
1.27e-04 2.37e+02 output
                  encoder.block.2.layer.1.DenseReluDense.dropout Dropout
0.00e+00 8.76e+03 input[0]
0.00e+00 9.74e+03 output
                  encoder.block.2.layer.1.DenseReluDense.wo Linear
1.01e-06 6.44e+00 weight
0.00e+00 9.74e+03 input[0]
3.18e-04 6.27e+04 output
                  encoder.block.2.layer.1.DenseReluDense T5DenseGatedGeluDense
1.79e-06 4.65e+00 input[0]
3.18e-04 6.27e+04 output
                  encoder.block.2.layer.1.dropout Dropout
3.18e-04 6.27e+04 input[0]
0.00e+00      inf output
```

İlk satır, hatanın oluştuğu parti numarasını gösterir. Bu durumda hata 0. partide oluşmuştur.

Her çerçeve, raporladığı modülü açıklar. Örneğin, aşağıdaki çerçeve, `encoder.block.2.layer.1.layer_norm` için rapor verir; bu, kodlayıcının ikinci bloğundaki birinci katmandaki katman normudur. İleri çağrılar `T5LayerNorm` içindir.

```shell
                  encoder.block.2.layer.1.layer_norm T5LayerNorm
8.69e-02 4.18e-01 weight
2.65e-04 3.42e+03 input[0]
1.79e-06 4.65e+00 output
```

Son kare, `DenseReluDense` sınıfı içindeki `dropout` özniteliğini çağıran `Dropout.forward` fonksiyonu hakkında bilgi veriyor. Taşma (`inf`), kodlayıcının ikinci bloğunda ilk partide gerçekleşti. En büyük girdi öğesi 6.27e+04 idi.

```shell
                  encoder.block.2.layer.1.DenseReluDense T5DenseGatedGeluDense
1.79e-06 4.65e+00 input[0]
3.18e-04 6.27e+04 output
                  encoder.block.2.layer.1.dropout Dropout
3.18e-04 6.27e+04 input[0]
0.00e+00      inf output
```

`T5DenseGatedGeluDense.forward` çıktı aktivasyonları 6.27e+04 maksimumuna ulaştı; bu değer, fp16'nın 6.4e+04 maksimumuna yakındır. Bir sonraki adımda `Dropout`, bazı öğeleri sıfırladıktan sonra ağırlıkları yeniden normalize eder, maksimum değeri 6.4e+04'ün üzerine iter ve taşmayı (overflow) tetikler.

Hatanın nerede oluştuğunu bildiğinize göre, [modeling_t5.py](https://github.com/huggingface/transformers/blob/main/src/transformers/models/t5/modeling_t5.py) içindeki modelleme kodunu inceleyin.

```py
class T5DenseGatedGeluDense(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.wi_0 = nn.Linear(config.d_model, config.d_ff, bias=False)
        self.wi_1 = nn.Linear(config.d_model, config.d_ff, bias=False)
        self.wo = nn.Linear(config.d_ff, config.d_model, bias=False)
        self.dropout = nn.Dropout(config.dropout_rate)
        self.gelu_act = ACT2FN["gelu_new"]

    def forward(self, hidden_states):
        hidden_gelu = self.gelu_act(self.wi_0(hidden_states))
        hidden_linear = self.wi_1(hidden_states)
        hidden_states = hidden_gelu * hidden_linear
        hidden_states = self.dropout(hidden_states)
        hidden_states = self.wo(hidden_states)
        return hidden_states
```

Bir çözüm, değerler çok büyük hale gelmeden birkaç adım önce fp32'ye geçmektir; böylece sayılar çarpıldığında veya toplanırken taşma olmaz. Bir diğer seçenek, karmaşıklık hassasiyetli eğitimi (`amp`) geçici olarak devre dışı bırakmaktır.

```py
import torch

def forward(self, hidden_states):
    device_type = hidden_states.device.type
    if torch.is_autocast_enabled(device_type):
        with torch.amp.autocast(device_type, enabled=False):
            return self._forward(hidden_states)
    else:
        return self._forward(hidden_states)
```

Rapor yalnızca tam karelerin girdilerini ve çıktılarını kapsar. Herhangi bir `forward` fonksiyonunun içindeki ara değerleri analiz etmek için, `forwarded_states` içindeki `inf` veya `nan` değerlerini izlemek amacıyla her forward çağrısından sonra `detect_overflow` ekleyin.

```py
from transformers.debug_utils import detect_overflow

class T5LayerFF(nn.Module):
    [...]

    def forward(self, hidden_states):
        forwarded_states = self.layer_norm(hidden_states)
        detect_overflow(forwarded_states, "after layer_norm")
        forwarded_states = self.DenseReluDense(forwarded_states)
        detect_overflow(forwarded_states, "after DenseReluDense")
        return hidden_states + self.dropout(forwarded_states)
```

[DebugUnderflowOverflow](/docs/transformers/v5.23.0/tr/internal/trainer_utils#transformers.debug_utils.DebugUnderflowOverflow) tarafından yazdırılan kare sayısını yapılandırın.

```py
from transformers.debug_utils import DebugUnderflowOverflow

debug_overflow = DebugUnderflowOverflow(model, max_frames_to_save=100)
```

### Toplu izleme

[DebugUnderflowOverflow](/docs/transformers/v5.23.0/tr/internal/trainer_utils#transformers.debug_utils.DebugUnderflowOverflow), taşma ve taşma altı algılama devre dışı bırakılarak her batch'teki mutlak minimum ve maksimum değerleri de izleyebilir. Bu, modelinizde değerlerin nerede sapmaya başladığını bulmanıza yardımcı olur.

Aşağıdaki örnek, 1 ve 3 numaralı partileri izler (partiler sıfır indekslidir).

```py
debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3])
```

```shell
                  *** Starting batch number=1 ***
abs min  abs max  metadata
                  shared Embedding
1.01e-06 7.92e+02 weight
0.00e+00 2.47e+04 input[0]
5.36e-05 7.92e+02 output
[...]
                  decoder.dropout Dropout
1.60e-07 2.27e+01 input[0]
0.00e+00 2.52e+01 output
                  decoder T5Stack
     not a tensor output
                  lm_head Linear
1.01e-06 7.92e+02 weight
0.00e+00 1.11e+00 input[0]
6.06e-02 8.39e+01 output
                   T5ForConditionalGeneration
     not a tensor output

                  *** Starting batch number=3 ***
abs min  abs max  metadata
                  shared Embedding
1.01e-06 7.92e+02 weight
0.00e+00 2.78e+04 input[0]
5.36e-05 7.92e+02 output
[...]
```

[DebugUnderflowOverflow](/docs/transformers/v5.23.0/tr/internal/trainer_utils#transformers.debug_utils.DebugUnderflowOverflow) birçok çerçeve raporlar, bu da değerlerin nerede ayrıştığını tespit etmeyi kolaylaştırır. Sorunun 150. parti civarında olduğunu biliyorsanız, sayıların farklılaşmaya başladığı noktayı karşılaştırmak için izlemeyi 149 ve 150. partilere odaklayın.

İzlemeyi belirli bir parti numarasından sonra da durdurabilirsiniz, örneğin 3. parti.

```py
debug_overflow = DebugUnderflowOverflow(model, trace_batch_nums=[1, 3], abort_after_batch_num=3)
```

## İletişim

Dağıtık eğitim, süreçler arası ve düğümler arası iletişimi gerektirir ve bu, yaygın bir hata kaynağıdır.

Aşağıdaki betiği indirerek ağ sorunlarını teşhis edin, ardından GPU iletişimini test etmek için çalıştırın. Aşağıdaki komut iki GPU'yu test eder. Sisteminize göre `--nproc_per_node` ve `--nnodes` değerlerini ayarlayın.

```bash
wget https://raw.githubusercontent.com/huggingface/transformers/main/scripts/distributed/torch-distributed-gpu-test.py
python -m torch.distributed.run --nproc_per_node 2 --nnodes 1 torch-distributed-gpu-test.py
```

Betik, her iki GPU da başarıyla iletişim kurup bellek ayırdıysa `OK` yazdırır. Daha fazla ayrıntı ve SLURM ortamında çalıştırma tarifi için tanı betiğine bakın.

Ayrıntılı NCCL hata ayıklama çıktısı almak için `NCCL_DEBUG=INFO` değerini ayarlayın.

```bash
NCCL_DEBUG=INFO python -m torch.distributed.run --nproc_per_node 2 --nnodes 1 torch-distributed-gpu-test.py
```

## DeepSpeed

Hata aldığınızda, önce DeepSpeed'in neden olup olmadığını kontrol edin. Kurulumunuzu DeepSpeed olmadan tekrar deneyin ve hata devam ederse sorunu bildirin. Transformers entegrasyonuyla ilgili olmayan sorunlar için DeepSpeed [deposunda](https://github.com/microsoft/DeepSpeed) bir sorun açın.

Transformers entegrasyonuyla ilgili sorunlar için aşağıdaki bilgileri ekleyin.

* Tam DeepSpeed yapılandırma dosyası.
* [Trainer](/docs/transformers/v5.23.0/tr/main_classes/trainer#transformers.Trainer) için komut satırı argümanları veya [Trainer](/docs/transformers/v5.23.0/tr/main_classes/trainer#transformers.Trainer) kurulumunu kendiniz script'leştirdiyseniz [TrainingArguments](/docs/transformers/v5.23.0/tr/main_classes/trainer#transformers.TrainingArguments) (birçok alakasız giriş içeren tüm [TrainingArguments](/docs/transformers/v5.23.0/tr/main_classes/trainer#transformers.TrainingArguments) nesnesini dökmemeye dikkat edin).
* Bu komutların çıktıları.

    ```bash
    python -c 'import torch; print(f"torch: {torch.__version__}")'
    python -c 'import transformers; print(f"transformers: {transformers.__version__}")'
    python -c 'import deepspeed; print(f"deepspeed: {deepspeed.__version__}")'
    ```

* Sorunu yeniden üretmek için bir Google Colab defterine bağlantı.
* Sorunu yeniden üretmek için standart veya özel olmayan bir veri seti veya mevcut bir örnek.

### Başlangıçta süreç öldürüldü

Eğer DeepSpeed süreci başlatma sırasında bir izleme (traceback) olmadan sonlandırılıyorsa, program mevcut veya izin verilen CPU belleğinden daha fazlasını tahsis etmeye çalışmıştır. Her iki durumda da işletim sistemi çekirdeği süreci sonlandırır.

Yapılandırma dosyanızda `offload_optimizer`, `offload_param` veya her ikisinin de CPU'ya taşımak üzere yapılandırılıp yapılandırılmadığını kontrol edin.

NVMe ve ZeRO-3 yapılandırmanız varsa, bunun yerine NVMe'ye offload etmeyi deneyin. Önce modelinizin bellek gereksinimlerini [tahmin edin](https://deepspeed.readthedocs.io/en/latest/memory.html).

### NaN kaybı

NaN kaybı, bir model bf16 ile ön eğitildikten sonra fp16 ile kullanıldığında sıkça görülür (bu durum TPU ile eğitilmiş modellerde özellikle yaygındır). Donanımınız destekliyorsa (TPU'lar, Ampere GPU'lar veya daha yenileri) fp32 veya bf16 kullanın.

fp16 taşma (overflow) da neden olabilir. Yapılandırma dosyanız aşağıdaki gibi görünüyorsa, günlüklerde taşma hataları görebilirsiniz.

```json
{
    "fp16": {
        "enabled": "auto",
        "loss_scale": 0,
        "loss_scale_window": 1000,
        "initial_scale_power": 16,
        "hysteresis": 2,
        "min_loss_scale": 1
    }
}
```

Aşağıdaki `OVERFLOW!` hatası, DeepSpeed kayıp ölçekleyicisinin kayıp taşmasını aşacak bir ölçekleme katsayısı bulamadığı anlamına gelir. Daha yüksek bir `initial_scale_power` değeri deneyin (32 genellikle işe yarar).

```bash
0%|                                                                                                                             | 0/189 [00:00<?, ?it/s]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 262144
  1%|▌                                                                                                                    | 1/189 [00:00<01:26,  2.17it/s]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 262144, reducing to 131072.0
  1%|█▏
 [...]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
 14%|████████████████▌                                                                                                   | 27/189 [00:14<01:13,  2.21it/s]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
 15%|█████████████████▏                                                                                                  | 28/189 [00:14<01:13,  2.18it/s]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
 15%|█████████████████▊                                                                                                  | 29/189 [00:15<01:13,  2.18it/s]
 [deepscale] OVERFLOW! Rank 0 Skipping step. Attempted loss scale: 1, reducing to 1
[...]
```

## DeepSpeed CUDA

DeepSpeed, CUDA gerektiren PyTorch eklentileri için derleme hatalarının yaygın bir kaynağı olan CUDA C++ kodu derler. Bu hatalar, CUDA'nın sisteminizde nasıl yüklendiğine bağlıdır.

```bash
pip install deepspeed
```

> [!TIP]
> Diğer tüm kurulum sorunları için DeepSpeed ekibiyle [bir sorun açın](https://github.com/microsoft/DeepSpeed/issues).

### Aynı olmayan araç setleri

PyTorch kendi CUDA araç setiyle birlikte gelir, ancak DeepSpeed, sistem genelinde kurulu olan CUDA sürümünün birebir aynı olmasını gerektirir. Python ortamınızda PyTorch'u `cudatoolkit==10.2` ile kurduysanız, her yerde CUDA 10.2'nin de kurulu olması gerekir.

Kesin konum sistemden sisteme değişir, ancak Unix sistemlerde en yaygın yol `/usr/local/cuda-10.2`'dir. CUDA kurulduktan ve `PATH` değişkenine eklendikten sonra, kurulum konumunu bu komutla bulabilirsiniz.

```bash
which nvcc
```

### Çoklu araç setleri

Sisteminizde birden fazla CUDA araç kiti yüklü olabilir.

```text
/usr/local/cuda-10.2
/usr/local/cuda-11.0
```

Paket kurucuları genellikle yolları son kurulan sürüme ayarlar. Derleme, doğru CUDA sürümünü bulamadığı için başarısız olursa, `PATH` ve `LD_LIBRARY_PATH` değişkenlerini doğru yola işaret edecek şekilde yapılandırın.

Önce bu ortam değişkenlerini kontrol edin.

```bash
echo $PATH
echo $LD_LIBRARY_PATH
```

`PATH` çalıştırılabilir dosya konumlarını listeler. `LD_LIBRARY_PATH` paylaşımlı kütüphane konumlarını listeler. Önceki girdiler önceliklidir ve birden fazla girdiyi `:` ayırır. Doğru CUDA yolunu başa ekleyerek önceliklendirin.

```bash
# adjust the version and full path if needed
export PATH=/usr/local/cuda-10.2/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda-10.2/lib64:$LD_LIBRARY_PATH
```

Atanan dizinlerin varlığını da doğrulayın. `lib64` alt dizini, `libcudart.so` gibi CUDA `.so` nesnelerini içerir. Gerçek dosya adlarını kontrol edin ve buna göre güncelleyin.

### Eski sürümler

Eski CUDA sürümleri bazen eski derleyici sürümleri gerektirir. Örneğin, CUDA `gcc-7` gerektiriyorsa ancak sisteminizde yalnızca `gcc-9` varsa, derleme işlemi başarısız olur. Gerekli eski derleyiciyi yükleyin ve CUDA derleme sisteminin onu bulabilmesi için bir sembolik bağlantı oluşturun.

```bash
# adjust the path to your system
sudo ln -s /usr/bin/gcc-7  /usr/local/cuda-10.2/bin/gcc
sudo ln -s /usr/bin/g++-7  /usr/local/cuda-10.2/bin/g++
```

### Ön derleme

Eğer DeepSpeed'i kurarken veya çalışma zamanında derlerken hâlâ sorun yaşıyorsanız, DeepSpeed modüllerini önceden derleyin. Yerel bir derleme için aşağıdaki komutları çalıştırın.

```bash
git clone https://github.com/deepspeedai/DeepSpeed/
cd DeepSpeed
rm -rf build
TORCH_CUDA_ARCH_LIST="8.6" DS_BUILD_CPU_ADAM=1 DS_BUILD_UTILS=1 pip install . \
--global-option="build_ext" --global-option="-j8" --no-cache -v \
--disable-pip-version-check 2>&1 | tee build.log
```

> [!TIP]
> NVMe offload kullanmak için derleme komutuna `DS_BUILD_AIO=1` ekleyin. libaio-dev paketinin sistem genelinde yüklendiğinden emin olun.

Ardından, GPU mimarinizi `TORCH_CUDA_ARCH_LIST` içinde ayarlayın. NVIDIA GPU'larının ve mimarilerinin tam listesi [CUDA GPU'ları sayfasında](https://developer.nvidia.com/cuda-gpus) yer alır. Mimarinize karşılık gelen PyTorch sürümünü kontrol etmek için aşağıdaki komutu çalıştırın.

```bash
python -c "import torch; print(torch.cuda.get_arch_list())"
```

Aşağıdaki komutla GPU'nun mimarisini bulun.

```bash
CUDA_VISIBLE_DEVICES=0 python -c "import torch; print(torch.cuda.get_device_capability())"
```

GPU `0` için mimariyi bulmak üzere aşağıdaki komutu çalıştırın. Çıktı, birlikte GPU mimarisini oluşturan `major` ve `minor` değerlerini gösterir. Aşağıdaki örnek, `8.6` mimarisini göstermektedir.

```bash
CUDA_VISIBLE_DEVICES=0 python -c "import torch; \
print(torch.cuda.get_device_properties(torch.device('cuda')))
"_CudaDeviceProperties(name='GeForce RTX 3090', major=8, minor=6, total_memory=24268MB, multi_processor_count=82)"
```

`8, 6` sonucu için `TORCH_CUDA_ARCH_LIST="8.6"` ayarlayın. Farklı mimarilere sahip birden çok GPU için bunları `TORCH_CUDA_ARCH_LIST="6.1;8.6"` gibi listeleyin.

`TORCH_CUDA_ARCH_LIST` öğesini atlayabilir ve derleme programının GPU mimarisini otomatik olarak algılamasına izin verebilirsiniz, ancak bu, hedef makinedeki gerçek GPU ile eşleşmeyebilir. Mimariyi açıkça belirtmek daha güvenilirdir.

Aynı yapılandırmaya sahip birden fazla makinede eğitim için, bir binary wheel oluşturun.

```bash
git clone https://github.com/deepspeedai/DeepSpeed/
cd DeepSpeed
rm -rf build
TORCH_CUDA_ARCH_LIST="8.6" DS_BUILD_CPU_ADAM=1 DS_BUILD_UTILS=1 \
python setup.py build_ext -j8 bdist_wheel
```

Bu, `dist/deepspeed-0.3.13+8cd046f-cp38-cp38-linux_x86_64.whl` gibi ikili bir tekerlek (wheel) oluşturur. Bunu yerel olarak veya başka bir makinede yükleyin.

```bash
pip install deepspeed-0.3.13+8cd046f-cp38-cp38-linux_x86_64.whl
```

