Accelerate documentation

Profiler

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

Profiler

Profiler adalah alat yang memungkinkan pengumpulan metrik kinerja selama pelatihan dan inferensi. API context manager dari Profiler dapat digunakan untuk memahami lebih baik operator model mana yang paling mahal, memeriksa bentuk input dan stack trace-nya, mempelajari aktivitas kernel perangkat, serta memvisualisasikan jejak eksekusi. Alat ini memberikan wawasan tentang kinerja model Anda, sehingga Anda dapat mengoptimalkan dan memperbaikinya.

Panduan ini menjelaskan cara menggunakan PyTorch Profiler untuk mengukur waktu dan konsumsi memori dari operator model, serta cara mengintegrasikannya dengan Accelerate. Kami akan membahas berbagai kasus penggunaan dan menyediakan contoh untuk masing-masing.

Menggunakan profiler untuk menganalisis waktu eksekusi

Profiler memungkinkan Anda memeriksa operator mana yang dipanggil selama eksekusi rentang kode yang dibungkus dengan context manager profiler.

Mari kita lihat bagaimana kita dapat menggunakan profiler untuk menganalisis waktu eksekusi:

PyTorch
Accelerate
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))

Hasil tabel yang dihasilkan (beberapa kolom dihilangkan):

---------------------------------  ------------  ------------  ------------  ------------  
                             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.016ms

Untuk mendapatkan granularitas hasil yang lebih halus dan menyertakan bentuk input operator, berikan group_by_input_shape=True (catatan: ini memerlukan menjalankan profiler dengan record_shapes=True):

print(prof.key_averages(group_by_input_shape=True).table(sort_by="cpu_time_total", row_limit=10))

Menggunakan profiler untuk menganalisis konsumsi memori

Profiler juga dapat menampilkan jumlah memori (yang digunakan oleh tensor model) yang dialokasikan (atau dilepaskan) selama eksekusi operator model. Untuk mengaktifkan fungsi profiling memori, berikan profile_memory=True.

PyTorch
Accelerate
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))

Hasil tabel yang dihasilkan (beberapa kolom dihilangkan):

---------------------------------  ------------  ------------  ------------  
                             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.332ms

Jika Anda membutuhkan satu atau dua angka agregat untuk pelacakan eksperimen alih-alih tabel operator lengkap, gabungkan profiler dengan statistik memori runtime yang diungkap oleh PyTorch. Hal ini sering kali sudah cukup untuk mencatat penggunaan memori puncak per eksekusi:

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

Pola ini menjaga keluaran profiler tetap tersedia untuk debugging sekaligus menghasilkan nilai ringkas yang dapat dicatat ke pelacak eksperimen.

Mengekspor jejak chrome

Anda dapat memeriksa urutan operator dan kernel CUDA yang diprofiling di Chrome trace viewer (chrome://tracing):

profile_export

PyTorch
Accelerate
# 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")

Menggunakan Profiler untuk Menganalisis Pekerjaan Berdurasi Panjang

Profiler menyediakan API tambahan untuk menangani tugas berdurasi panjang (seperti loop pelatihan). Melacak seluruh eksekusi dapat menjadi lambat dan menghasilkan file trace yang sangat besar. Untuk menghindari hal ini, gunakan argumen opsional:

  • schedule_option: Opsi penjadwalan memungkinkan Anda mengontrol kapan profiling aktif. Ini berguna untuk tugas yang berjalan lama agar tidak mengumpulkan terlalu banyak data. Kunci yang tersedia adalah wait, warmup, active, repeat, dan skip_first. Profiler akan melewati skip_first langkah pertama, kemudian menunggu selama wait langkah, kemudian melakukan pemanasan selama warmup langkah berikutnya, kemudian melakukan perekaman aktif selama active langkah berikutnya, dan kemudian mengulang siklus mulai dari wait langkah. Jumlah siklus opsional ditentukan dengan parameter repeat; nilai nol berarti siklus akan terus berlanjut hingga profiling selesai.
  • on_trace_ready: menentukan fungsi yang menerima referensi ke profiler sebagai input dan dipanggil oleh profiler setiap kali trace baru siap.

Untuk mengilustrasikan cara kerja API, pertimbangkan contoh berikut:

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

FLOPS

Gunakan rumus untuk memperkirakan FLOPs (floating point operations) dari operator tertentu (perkalian matriks dan konvolusi 2D).

Untuk mengukur operasi bilangan pecahan mengambang (FLOPS):

PyTorch
Accelerate
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))

Hasil tabel yang dihasilkan (beberapa kolom dihilangkan):

-------------------------------------------------------  ------------  ------------  ------------  
                                                   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.165ms

Kesimpulan dan Informasi Lanjutan

PyTorch Profiler adalah alat yang ampuh untuk menganalisis kinerja model Anda. Dengan mengintegrasikannya dengan Accelerate, Anda dapat dengan mudah memprofil model Anda dan mendapatkan wawasan tentang kinerjanya, yang membantu Anda mengoptimalkan dan memperbaikinya.

Untuk informasi yang lebih detail, lihat dokumentasi PyTorch Profiler.

Update on GitHub