Half-Precision
Yarı duyarlık (FP16), sayıları FP32'nin 32 biti yerine 16 bit ile saklar; böylece bellek kullanımı yarıya iner ve GPU hesaplamaları hızlanır. Sınırlamaları, kayıp ölçeklendirme ve FP16 çıkarımı.
Yarım duyarlılık olarak da bilinen FP16, float16 veya IEEE 754 binary16, 1 işaret biti, 5 üs biti ve 10 kesir bitinden oluşan 16 bitlik bir kayan nokta biçimidir. Standart 32 bit tek duyarlıkla (FP32) karşılaştırıldığında her sayının gerektirdiği bellek ve bant genişliğini yarıya indirir; Tensor Core içeren GPU'lar, FP16 matris hesaplamalarını FP32'den çok daha hızlı gerçekleştirir. Bunun karşılığında aralık daralır; en büyük değer 65.504'tür ve yaklaşık üç anlamlı ondalık basamak sunar. Sinir ağları bu yuvarlamayı iyi tolere eder; bu nedenle FP16, GPU çıkarımında standart duyarlılık ve karma duyarlılıkla birlikte eğitimi hızlandırmanın yaygın bir yoludur.
FP16 ile FP32 Karşılaştırması#
FP32, üs için 8 bit, kesir için 23 bit kullanır; böylece yaklaşık 10⁻³⁸ ile 10³⁸ arasında bir aralığı ve yaklaşık yedi anlamlı basamağı kapsar. FP16'nın 5 üs biti, normal değerleri 6.1 × 10⁻⁵ ile 65.504 arasında sınırlar; daha küçük alt normal değerler ise düşük duyarlılıkla yaklaşık 6 × 10⁻⁸'e kadar iner. Daha büyük her değer sonsuza taşar, daha küçük her değer sıfıra yuvarlanır. Bir modeli dönüştürmek hem avantajı hem de sınırları gösterir:
import torch
import torchvision
# ResNet-18 stores its weights in FP32 by default
model = torchvision.models.resnet18()
fp32_mb = sum(p.numel() * p.element_size() for p in model.parameters()) / 1e6
# Casting to FP16 stores every weight in 2 bytes instead of 4
model.half()
fp16_mb = sum(p.numel() * p.element_size() for p in model.parameters()) / 1e6
print(f"Weights: {fp32_mb:.1f} MB in FP32, {fp16_mb:.1f} MB in FP16")
# FP16 overflows above 65,504 and rounds to about 3 significant digits
x = torch.tensor([65504.0, 70000.0, 0.1])
print("FP16 values:", x.half().tolist())Ağırlıklar 46.8 MB'den 23.4 MB'ye düşer. İkinci satırda 65.504 en büyük FP16 değeri olarak korunur, 70.000 inf olur ve 0.1, FP16'nın temsil edebildiği en yakın değer olan 0.0999755859375 olarak saklanır.
Eğitimde Yarım Duyarlılık#
Tamamen FP16 ile eğitim, küçük gradyanların sıfıra taşması ve ağırlıklara kıyasla çok küçük ağırlık güncellemelerinin yuvarlanarak kaybolması nedeniyle birçok modelde doğruluk kaybına veya yakınsamama durumuna yol açar. Karma duyarlıklı eğitim her iki sorunu da çözer: güncellemeler için ağırlıkların FP32 ana kopyasını tutar, ileri ve geri yayılım geçişlerini FP16'da yürütür ve gradyanları FP32'de ölçeğini geri almadan önce FP16 aralığında tutmak için kaybı bir ölçek faktörüyle çarpar. PyTorch'un GradScaler özelliğinde olduğu gibi, çerçeveler bu faktörü otomatik olarak ayarlar:
FP16 etkinleştirmeleri, eğitim sırasında bir yığının kullandığı belleği de yarıya indirir; böylece aynı GPU daha büyük yığınlara veya daha yüksek çözünürlüklü girdilere yer açar. Destekleyen donanımlarda, FP32 boyutundaki üssü kayıp ölçeklendirme gereksinimini ortadan kaldırdığı için bfloat16 (BF16) genellikle eğitimde tercih edilir.
Çıkarımda Yarım Duyarlılık#
Çıkarım için gradyanlara ihtiyaç duyulmaz ve çoğu bilgisayarlı görü modelindeki aktivasyon değerleri FP16'nın temsil aralığının rahatça içinde kalır; bu nedenle tamamlanmış bir modeli FP16'ya dönüştürmek, INT8 model nicelemesinin gerektirdiği kalibrasyon verileri olmadan genellikle doğruluğu FP32 düzeyine çok yakın tutar. TensorRT gibi GPU çıkarım altyapıları, Tensor Cores üzerinde çalışan FP16 motorları oluşturur ve NVIDIA Jetson gibi gömülü GPU'lar gerçek zamanlı çıkarım için FP16'ya dayanır. CPU'larda kazanım daha sınırlıdır, çünkü çoğunda hızlı FP16 aritmetiği bulunmaz. Ultralytics YOLO, varsayılan olarak GPU'larda FP16 karma duyarlılıkla eğitim yapar (amp=True) ve quantize=16 ile FP16 tahmini ve dışa aktarma işlemlerini gerçekleştirir; örneğin YOLO26 ile:
from ultralytics import YOLO
# En küçük YOLO26 algılama modelini yükle
model = YOLO("yolo26n.pt")
# GPU'da FP16 ile tahmin yap; CPU'da PyTorch modelleri FP32'de çalışır
results = model.predict("https://ultralytics.com/images/bus.jpg", quantize=16)
# Ağırlıklarını FP16 olarak saklayan bir ONNX modeli dışa aktar
path = model.export(format="onnx", quantize=16)Dışa aktarılan dosyada her ağırlık 4 yerine 2 baytla saklanır. Aynı quantize=16 bağımsız değişkeni, TensorRT, OpenVINO, CoreML ve diğer dışa aktarma biçimleri için FP16 modeller üretir.
Yarım Duyarlılık ve İlgili Biçimler#
- BFloat16 (BF16): Diğer 16 bitlik kayan nokta biçimidir; 8 üs ve 7 kesir bitiyle FP32'nin aralığını korurken duyarlılıktan ödün verir ve büyük modelleri eğitirken tercih edilir.
- FP8: Yeni NVIDIA GPU'larda kullanılan, belleği bir kez daha yarıya indiren 8 bitlik kayan nokta biçimleridir; çoğunlukla büyük dil modellerini eğitmek ve sunmak için kullanılır.
- INT8 niceleme: Değerleri tensör başına veya kanal başına ölçeklerle 8 bitlik tam sayılara dönüştürür. FP16'dan daha hızlı ve küçüktür; ancak doğruluğu korumak için kalibrasyon verileri veya niceleme farkındalıklı eğitim gerekir.
Yarım Duyarlılığın Kullanım Alanları#
- Uç yapay zekâ: Jetson modüllerindeki ve diğer gömülü GPU'lardaki algılayıcılar, birkaç watt ya da onlarca watt güç tüketimiyle kamera kare hızlarına ulaşmak için FP16'da çalışır.
- Bulut çıkarımı: FP16 ile sunum yapmak, model kopyası başına belleği yarıya indirir; böylece tek bir GPU daha fazla kopya veya daha büyük yığın barındırır.
- Büyük dil modelleri: 7 milyar parametreli bir modelin ağırlıkları FP32'de 28 GB, FP16'da 14 GB alan gerektirir; bu nedenle FP16 ile tek bir 24 GB tüketici GPU'suna KV önbelleği için de yer kalacak şekilde sığar.










