Accelerate documentation
Profil Oluşturucu
Profil Oluşturucu
Profiler, eğitim ve çıkarım sırasında performans metriklerinin toplanmasına olanak tanıyan bir araçtır. Profiler'ın bağlam yöneticisi API'si, en pahalı model operatörlerini daha iyi anlamak, girdi şekillerini ve yığın izlerini incelemek, cihaz çekirdeği etkinliğini araştırmak ve yürütme izini görselleştirmek için kullanılabilir. Modelinizin performansına dair içgörüler sağlayarak onu optimize etmenize ve geliştirmenize olanak tanır.
Bu kılavuz, modelin operatörlerinin zaman ve bellek tüketimini ölçmek için PyTorch Profiler'ın nasıl kullanılacağını ve bunun Accelerate ile nasıl entegre edileceğini açıklar. Çeşitli kullanım senaryilerini ele alacak ve her biri için örnekler sunacağız.
Çalışma süresini analiz etmek için profiler kullanımı
Profiler, bir profiler bağlam yöneticisiyle sarılmış bir kod aralığının çalıştırılması sırasında hangi operatörlerin çağrıldığını kontrol etmenizi sağlar.
Profilleyicinin (profiler) çalışma süresini analiz etmek için nasıl kullanabileceğimize bakalım:
import torch
import torchvision.models as models
from torch.profiler import profile, record_function, ProfilerActivity
model = models.resnet18()
inputs = torch.randn(5, 3, 224, 224)
with profile(activities=[ProfilerActivity.CPU], record_shapes=True) as prof:
model(inputs)
print(prof.key_averages().table(sort_by="cpu_time_total", row_limit=10))from accelerate import Accelerator, ProfileKwargs
import torch
import torchvision.models as models
model = models.resnet18()
inputs = torch.randn(5, 3, 224, 224)
profile_kwargs = ProfileKwargs(
activities=["cpu"],
record_shapes=True
)
accelerator = Accelerator(cpu=True, kwargs_handlers=[profile_kwargs])
model = accelerator.prepare(model)
with accelerator.profile() as prof:
with torch.no_grad():
model(inputs)
print(prof.key_averages().table(sort_by="cpu_time_total", row_limit=10))Sonuç olarak elde edilen tablo çıktısı (bazı sütunlar hariç):
--------------------------------- ------------ ------------ ------------ ------------
Name Self CPU CPU total CPU time avg # of Calls
--------------------------------- ------------ ------------ ------------ ------------
aten::conv2d 171.000us 52.260ms 2.613ms 20
aten::convolution 227.000us 52.089ms 2.604ms 20
aten::_convolution 270.000us 51.862ms 2.593ms 20
aten::mkldnn_convolution 51.273ms 51.592ms 2.580ms 20
aten::batch_norm 118.000us 7.059ms 352.950us 20
aten::_batch_norm_impl_index 315.000us 6.941ms 347.050us 20
aten::native_batch_norm 6.305ms 6.599ms 329.950us 20
aten::max_pool2d 40.000us 4.008ms 4.008ms 1
aten::max_pool2d_with_indices 3.968ms 3.968ms 3.968ms 1
aten::add_ 780.000us 780.000us 27.857us 28
--------------------------------- ------------ ------------ ------------ ------------
Self CPU time total: 67.016msDaha ince bir sonuç granülerliği elde etmek ve operatör giriş şekillerini dahil etmek için group_by_input_shape=True parametresini iletin (not: bunun için profilleyicinin record_shapes=True ile çalıştırılması gerekir):
print(prof.key_averages(group_by_input_shape=True).table(sort_by="cpu_time_total", row_limit=10))Bellek tüketimini analiz etmek için profiler kullanımı
Profiler, model operatörlerinin çalıştırılması sırasında tahsis edilen (veya serbest bırakılan) bellek miktarını (modelin tensörleri tarafından kullanılan) da gösterebilir. Bellek profilleme işlevini etkinleştirmek için profile_memory=True parametresini iletin.
model = models.resnet18()
inputs = torch.randn(5, 3, 224, 224)
with profile(activities=[ProfilerActivity.CPU],
profile_memory=True, record_shapes=True) as prof:
model(inputs)
print(prof.key_averages().table(sort_by="self_cpu_memory_usage", row_limit=10))model = models.resnet18()
inputs = torch.randn(5, 3, 224, 224)
profile_kwargs = ProfileKwargs(
activities=["cpu"],
profile_memory=True,
record_shapes=True
)
accelerator = Accelerator(cpu=True, kwargs_handlers=[profile_kwargs])
model = accelerator.prepare(model)
with accelerator.profile() as prof:
model(inputs)
print(prof.key_averages().table(sort_by="self_cpu_memory_usage", row_limit=10))Sonuç olarak elde edilen tablo çıktısı (bazı sütunlar hariç):
--------------------------------- ------------ ------------ ------------
Name CPU Mem Self CPU Mem # of Calls
--------------------------------- ------------ ------------ ------------
aten::empty 94.85 Mb 94.85 Mb 205
aten::max_pool2d_with_indices 11.48 Mb 11.48 Mb 1
aten::addmm 19.53 Kb 19.53 Kb 1
aten::mean 10.00 Kb 10.00 Kb 1
aten::empty_strided 492 b 492 b 5
aten::cat 240 b 240 b 6
aten::abs 480 b 240 b 4
aten::masked_select 120 b 112 b 1
aten::ne 61 b 53 b 3
aten::eq 30 b 30 b 1
--------------------------------- ------------ ------------ ------------
Self CPU time total: 69.332msDeneysel izleme için tam bir operatör tablosu yerine bir veya iki toplam sayıya ihtiyacınız varsa, profilleyiciyi PyTorch tarafından açığa çıkarılan çalışma zamanı bellek istatistikleriyle birleştirebilirsiniz. Bu, genellikle çalıştırma başına tepe bellek kullanımını günlüğe kaydetmek için yeterlidir:
import torch
from accelerate import Accelerator, PartialState, ProfileKwargs
# Resolve the device type/module (cuda, xpu, ...) instead of hardcoding CUDA
device_type = PartialState().device.type
device_module = getattr(torch, device_type)
def summarize_memory_stats():
return {
"peak_allocated_mb": device_module.max_memory_allocated() / 1024**2,
"peak_reserved_mb": device_module.max_memory_reserved() / 1024**2,
}
profile_kwargs = ProfileKwargs(
activities=["cpu", device_type],
profile_memory=True,
record_shapes=True,
)
accelerator = Accelerator(kwargs_handlers=[profile_kwargs])
device_module.reset_peak_memory_stats()
with accelerator.profile() as prof:
model(inputs)
print(prof.key_averages().table(sort_by=f"self_{device_type}_memory_usage", row_limit=10))
print(summarize_memory_stats())Bu desen, profilleyici çıktısını hata ayıklama için erişilebilir tutarken, bir deney izleyicisine kaydedilebilecek kompakt değerler de üretir.
Chrome izini dışa aktarma
Chrome trace görüntüleyicisinde (chrome://tracing) profillenmiş operatörlerin ve CUDA çekirdeklerinin sırasını inceleyebilirsiniz:
# Pick the available accelerator (cuda, xpu, ...) instead of hardcoding CUDA
device = torch.accelerator.current_accelerator()
device_activity = getattr(ProfilerActivity, device.type.upper())
model = models.resnet18().to(device)
inputs = torch.randn(5, 3, 224, 224).to(device)
with profile(activities=[ProfilerActivity.CPU, device_activity]) as prof:
model(inputs)
prof.export_chrome_trace("trace.json")model = models.resnet18()
profile_kwargs = ProfileKwargs(
activities=["cpu", PartialState().device.type],
output_trace_dir="trace"
)
accelerator = Accelerator(kwargs_handlers=[profile_kwargs])
model = accelerator.prepare(model)
inputs = torch.randn(5, 3, 224, 224).to(accelerator.device)
with accelerator.profile() as prof:
model(inputs)
# The trace will be saved to the specified directoryUzun Süreli İşleri Analiz Etmek İçin Profiler Kullanımı
Profiler, uzun süreli işleri (eğitim döngüleri gibi) işlemek için ek bir API sunar. Tüm çalışmayı izlemek yavaş olabilir ve çok büyük izleme dosyalarına yol açabilir. Bunu önlemek için isteğe bağlı argümanları kullanın:
schedule_option: Zamanlama seçenekleri, profillemenin ne zaman etkin olacağını kontrol etmenizi sağlar. Bu, uzun süreli işlerde çok fazla veri toplanmasını önlemek için kullanışlıdır. Kullanılabilir anahtarlarwait,warmup,active,repeatveskip_first'tir. Profiler, ilkskip_firstadımı atlar, ardındanwaitadım bekler, sonrakiwarmupadım için ısınma yapar, sonrakiactiveadım için etkin kayıt yapar ve ardındanwaitadımıyla başlayarak döngüyü tekrarlar. İsteğe bağlı döngü sayısırepeatparametresiyle belirtilir; sıfır değeri, döngülerin profilleme tamamlanana kadar devam edeceği anlamına gelir.on_trace_ready: Profiler referansını girdi olarak alan ve her yeni izleme hazır olduğunda profiler tarafından çağrılan bir işlev belirtir.
API'nin nasıl çalıştığını göstermek için aşağıdaki örneği inceleyin:
from torch.profiler import schedule
my_schedule = schedule(
skip_first=1,
wait=5,
warmup=1,
active=3,
repeat=2
)
def trace_handler(p):
output = p.key_averages().table(sort_by=f"self_{device.type}_time_total", row_limit=10)
print(output)
p.export_chrome_trace("/tmp/trace_" + str(p.step_num) + ".json")
with profile(
activities=[ProfilerActivity.CPU, device_activity],
schedule=my_schedule,
on_trace_ready=trace_handler
) as p:
for idx in range(8):
model(inputs)
p.step()device_type = PartialState().device.type
def trace_handler(p):
output = p.key_averages().table(sort_by=f"self_{device_type}_time_total", row_limit=10)
print(output)
p.export_chrome_trace("/tmp/trace_" + str(p.step_num) + ".json")
profile_kwargs = ProfileKwargs(
activities=["cpu", device_type],
schedule_option={"wait": 5, "warmup": 1, "active": 3, "repeat": 2, "skip_first": 1},
on_trace_ready=trace_handler
)
accelerator = Accelerator(kwargs_handlers=[profile_kwargs])
model = accelerator.prepare(model)
with accelerator.profile() as prof:
for idx in range(8):
model(inputs)
prof.step()FLOPS
Belirli operatörlerin (matris çarpımı ve 2D konvolüsyon) FLOPs (kayan nokta işlemleri) değerlerini tahmin etmek için formülü kullanın.
Yüzen noktalı işlemleri (FLOPS) ölçmek için:
with profile(
activities=[ProfilerActivity.CPU, device_activity],
with_flops=True
) as prof:
model(inputs)
print(prof.key_averages().table(sort_by="flops", row_limit=10))profile_kwargs = ProfileKwargs(
with_flops=True
)
accelerator = Accelerator(kwargs_handlers=[profile_kwargs])
with accelerator.profile() as prof:
model(inputs)
print(prof.key_averages().table(sort_by="flops", row_limit=10))Sonuç olarak elde edilen tablo çıktısı (bazı sütunlar hariç):
------------------------------------------------------- ------------ ------------ ------------
Name Self CPU Self CUDA Total FLOPs
------------------------------------------------------- ------------ ------------ ------------
aten::conv2d 197.000us 0.000us 18135613440.000
aten::addmm 103.000us 17.000us 5120000.000
aten::mul 29.000us 2.000us 30.000
aten::convolution 409.000us 0.000us --
aten::_convolution 253.000us 0.000us --
aten::cudnn_convolution 5.465ms 2.970ms --
cudaEventRecord 138.000us 0.000us --
cudaStreamIsCapturing 43.000us 0.000us --
cudaStreamGetPriority 40.000us 0.000us --
cudaDeviceGetStreamPriorityRange 10.000us 0.000us --
------------------------------------------------------- ------------ ------------ ------------
Self CPU time total: 21.938ms
Self CUDA time total: 4.165msSonuç ve Daha Fazla Bilgi
PyTorch Profiler, modellerinizin performansını analiz etmek için güçlü bir araçtır. Bunu Accelerate ile entegre ederek modellerinizi kolayca profilleme yapabilir ve performanslarına dair içgörüler kazanarak bunları optimize etmenize ve iyileştirmenize yardımcı olabilirsiniz.
Daha ayrıntılı bilgi için PyTorch Profiler belgelerine başvurun.
Update on GitHub