Middle
Pythonдеги GIL (Global Interpreter Lock) эмне?
sobes.tech AI
AIден жооп
GIL (Global Interpreter Lock) — бул CPython интерпретаторундагы механизм, ал бир учурда гана бир жип (thread) иштешине уруксат берет. Көп ядролуу процессорлордо да, GIL жиптерге Python кодун чын эле параллелдүү иштетүүгө мүмкүнчүлүк бербейт.
GILдин бар болуу себептери:
- Эстутумду башкарууну жөнөкөйлөтүү: GIL жиптер менен ишенимдүү эстутумду башкаруу жана мусор чогултууну (reference counting) жеңилдетет. GIL жок болсо, жалпы структураларды коргоо үчүн көбүрөөк жана кымбат механизмдер керек болмок.
- C китепканалар менен шайкештикти сактоо: GIL бар болсо, C тилинде жазылган китепканалар менен интеграция жеңил болот, алар көп жиптүү иштөө үчүн ылайыкташпашы мүмкүн.
GILдин таасири:
- CPU-байланыштуу тапшырмалардын параллелизмин чектөө: CPU-га интенсивдүү колдонулган тапшырмаларда, GIL чектөө болуп калат, анткени көп ядролуу системаларда да иштетүү ядролор арасында параллелдүү болбойт. Жиптер GIL бошотулушун күтүшү керек.
- I/O-байланыштуу тапшырмаларга аз таасир: I/O операцияларын интенсивдүү колдонгон тапшырмаларда (желелүү суроолор, файлдар менен иштөө), GIL азыраак мааниге ээ. I/O операциялары учурунда, жип GIL бошотуп, башка жиптер иштей алат.
GILден качуу жолдору:
- Көп процессорлуулук (Multiprocessing): Жиптердин ордуна, көзкарандысыз процесстер колдонулат. Ар бир процессте өзүнүн Python интерпретатору жана GIL бар. Процесстер ар башка ядролордо параллелдүү иштей алат.
- Асинхрон программалоо (asyncio): Бир жипте асинхрондук киргизүү-чыгаруу моделин колдонуу. Много жип түзүүнүн ордуна, асинхрон код күтүүлөр учурунда тапшырмалар арасында которулуп турат. GIL бул учурда көп таасир этпейт, анткени CPU-га байланыштуу тапшырмалар параллелдүү иштебейт.
- C/C++ китепканалары: Кээ бир C же C++ код бөлүктөрү GIL кармабастан операцияларды аткара алат, аларды иштетүү учурунда бошотуп коюшу мүмкүн. NumPy жана SciPy сыяктуу популярдуу китепканалар бул ыкманы натыйжалуу эсептөөлөр үчүн колдонушат.
# GILдин CPU-байланыштуу тапшырмага таасири мисалы
import threading
import time
def cpu_bound_task():
count = 0
for i in range(10**7):
count += 1
# CPU-байланыштуу тапшырма үчүн эки жип түзүү
t1 = threading.Thread(target=cpu_bound_task)
t2 = threading.Thread(target=cpu_bound_task)
баштоо убактысы = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
аякталган убакыт = time.time()
print(f"Жиптер менен аткаруу убактысы (CPU-байланыштуу): {аякталган убакыт - баштоо убактысы:.2f} секунд") # Убакыт эки эсеге көбөйөт, GIL себептүү
# I/O-байланыштуу тапшырма мисалы, GIL азыраак байкалат
import threading
import time
def io_bound_task():
time.sleep(1) # I/O күтүүнү имитациялоо
# I/O-байланыштуу тапшырма үчүн эки жип түзүү
t1 = threading.Thread(target=io_bound_task)
t2 = threading.Thread(target=io_bound_task)
баштоо убактысы = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
аякталган убакыт = time.time()
print(f"Жиптер менен аткаруу убактысы (I/O-bound): {аякталган убакыт - баштоо убактысы:.2f} секунд") # Убакыт 1 секундга жакын болот, анткени жиптер sleep учурунда GIL бошотуп коет