Penghias ialah pelaksanaan khusus pengurus konteks python. Artikel ini akan menggambarkan cara menggunakannya melalui contoh penyahpepijatan GPU pytorch. Walaupun ia mungkin tidak berfungsi dalam setiap keadaan, saya dapati ia sangat berguna.
Terdapat banyak cara untuk nyahpepijat kebocoran memori. Artikel ini akan menunjukkan kaedah yang berguna untuk mengenal pasti baris bermasalah dalam kod anda. Kaedah ini boleh membantu mencari lokasi tertentu dengan cara yang ringkas.
Jika anda menghadapi masalah, kaedah klasik dan biasa digunakan ialah menggunakan penyahpepijat untuk menyemak baris demi baris, seperti contoh berikut:
Ia berfungsi, tetapi ia kelihatan seperti banyak masalah. Kita boleh merangkumnya ke dalam fungsi, yang boleh dipanggil apabila diperlukan, jadi hampir tidak perlu mengubah suai kod sedia ada, yang membawa kita untuk memperkenalkan fungsi penghias.
Dekorator boleh dibungkus dalam mana-mana bahagian kod. Di sini kita menggunakan alat penghias untuk memeriksa sama ada terdapat tensor tambahan Selain itu, kita juga memerlukan pembilang kerana bilangan tensor perlu dikira sebelum dan selepas pelaksanaan. Coraknya kelihatan seperti ini:
def memleak_wrapper(func): def wrap(*args, **kwargs): print("num tensors start is ...") out = func(*args, **kwargs) print("num tensors end is ...") return out return wrap@memleak_wrapper def function_to_debug(x): print(f"put line(s) of code here. Input is {x}") out = x + 10 return outout = function_to_debug(x=1000) print(f"out is {out}") #输入类似这样 #num tensors start is ... #put line(s) of code here. Input is 1000 #num tensors end is ... #outis 1010
Untuk menjalankan kod ini, kita perlu meletakkan baris kod yang ingin kita semak ke dalam fungsi (function_to_debug). Tetapi ini bukanlah yang terbaik kerana kita masih perlu memasukkan banyak kod secara manual. Perkara lain ialah jika blok kod menjana lebih daripada satu pembolehubah, anda perlu mencari penyelesaian tambahan untuk menggunakan pembolehubah hiliran ini.
Untuk menyelesaikan masalah di atas, kita boleh menggunakan pengurus konteks dan bukannya penghias fungsi. Contoh pengurus konteks yang paling banyak digunakan ialah membuat konteks menggunakan pernyataan dengan. Yang paling biasa digunakan ialah:
with open("file") as f: …
Menggunakan perpustakaan contextlib Python, pengguna Python boleh membuat pengurus konteks mereka sendiri dengan mudah. Jadi dalam artikel ini kami akan menggunakan ContextDecorator untuk menyelesaikan kerja yang kami cuba gunakan penghias di atas. Kerana ia lebih mudah untuk dibangunkan dan lebih mudah digunakan:
from contextlib import ContextDecorator class check_memory_leak_context(ContextDecorator): def __enter__(self): print('Starting') return self def __exit__(self, *exc): print('Finishing') return False
ContextDecorator mempunyai 2 kaedah: enter() dan exit() , yang dipanggil apabila kita masuk atau keluar dari konteks. Parameter *exc dalam __exit__ mewakili sebarang pengecualian masuk.
Sekarang mari gunakannya untuk menyelesaikan masalah yang dinyatakan di atas.
Oleh kerana kita perlu mengira jumlah bilangan tensor, kita merangkum proses pengiraan ke dalam fungsi get_n_tensors(), supaya tensor boleh dikira pada permulaan dan akhir konteks Kuantiti amaun:
class check_memory_leak_context(ContextDecorator): def __enter__(self): self.start = get_n_tensors() return self def __exit__(self, *exc): self.end = get_n_tensors() increase = self.end — self.start if increase > 0: print(f”num tensors increased with" f"{self.end — self.start} !”) else: print(”no added tensors”) return False
Jika terdapat peningkatan, cetak ke konsol.
get_n_tensor() menggunakan pemungut sampah (gc) dan disesuaikan untuk pytorch, tetapi boleh diubah suai dengan mudah untuk perpustakaan lain:
import gc def get_n_tensors(): tensors= [] for obj in gc.get_objects(): try: if (torch.is_tensor(obj) or (hasattr(obj, ‘data’) and torch.is_tensor(obj.data))): tensors.append(obj) except: pass return len(tensors)
Ia sedia untuk digunakan sekarang, kami Gunakan ini konteks untuk mana-mana baris (atau blok) kod:
x = arbitrary_operation(x) ... with check_memory_leak_context(): y = x[0].permute(1, 2, 0).cpu().detach().numpy() x = some_harmless_operation() ... x = another_arbitrary_operation(x)
Jika tensor baharu dicipta dalam baris yang dibalut oleh penghias konteks, ia akan dicetak.
Ini adalah coretan kod yang sangat bagus yang boleh anda letakkan dalam fail berasingan semasa pembangunan Berikut ialah kod lengkap untuk artikel ini:
https://. gist.github.com/MarkTension/4783697ebd5212ba500cdd829b364338
Akhir sekali, saya harap artikel kecil ini dapat membantu anda memahami maksud pengurus konteks, cara menggunakan penghias konteks dan cara menggunakannya untuk menyahpepijat pytorch .
Atas ialah kandungan terperinci Menyahpepijat isu kebocoran memori Pytorch menggunakan penghias konteks. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!