Neden Global Tercüman Kilidi?


89

Python'un Global Tercüman Kilidinin işlevi tam olarak nedir? Bayt koduna göre derlenen diğer diller benzer bir mekanizma kullanıyor mu?


6
Ayrıca "Fark eder mi?" Diye sormalısınız.
S.Lott

2
Katılıyorum, 2.6'da çoklu işlem modülünün iş parçacığı benzeri bir şekilde birden çok işlemi kullanarak programlamanıza izin vermek için eklendiğini artık bir sorun olmadığını düşünüyorum. docs.python.org/library/multiprocessing.html
monkut

Yanıtlar:


69

Genel olarak, herhangi bir iş parçacığı güvenliği sorunu için dahili veri yapılarınızı kilitlerle korumanız gerekecektir. Bu, çeşitli ayrıntı düzeyleriyle yapılabilir.

  • Her ayrı yapının kendi kilidine sahip olduğu ince taneli kilitlemeyi kullanabilirsiniz.

  • Tek bir kilidin her şeyi koruduğu (GIL yaklaşımı) kaba taneli kilitlemeyi kullanabilirsiniz.

Her yöntemin çeşitli artıları ve eksileri vardır. İnce taneli kilitleme, daha fazla paralellik sağlar - iki iş parçacığı, herhangi bir kaynağı paylaşmadıklarında paralel olarak yürütülebilir. Ancak çok daha büyük bir idari ek yük var. Her kod satırı için birkaç kilit almanız ve bırakmanız gerekebilir.

Kaba taneli yaklaşım bunun tersidir. İki iş parçacığı aynı anda çalışamaz, ancak tek bir iş parçacığı daha hızlı çalışır çünkü çok fazla muhasebe yapmaz. Sonuçta, tek iş parçacıklı hız ve paralellik arasında bir değiş tokuşa varılır.

Python'da GIL'i kaldırmak için birkaç girişimde bulunuldu, ancak tek iş parçacıklı makineler için fazladan yük genellikle çok büyüktü. Kilit çekişmesi nedeniyle bazı durumlar çok işlemcili makinelerde bile daha yavaş olabilir.

Bayt koduna göre derlenen diğer diller benzer bir mekanizma kullanıyor mu?

Değişiklik gösterir ve muhtemelen bir uygulama özelliği kadar bir dil özelliği olarak düşünülmemelidir. Örneğin, Jython ve IronPython gibi bir GIL yaklaşımı yerine temeldeki sanal makinelerinin iş parçacığı yaklaşımını kullanan Python uygulamaları vardır. Ek olarak, Ruby'nin bir sonraki sürümü bir GIL sunmaya doğru ilerliyor gibi görünüyor .


1
bunu açıklayabilir misin: 'İki iş parçacığı aynı anda çalışamaz'? Son zamanlarda Python'da çoklu okuma ile basit bir web sunucusu yazdım. İstemciden gelen her yeni istek için, sunucular onun için yeni bir iş parçacığı oluşturur ve bu iş parçacığı çalışmaya devam eder. Yani aynı anda çalışan birden fazla iş parçacığı olacak değil mi? Yoksa yanlış bir şekilde mi anladım?
avi

1
@avi AFAIK python iş parçacıkları aynı anda çalışamaz, ancak bu bir iş parçacığının diğerini engellemesi gerektiği anlamına gelmez. GIL, yalnızca bir iş parçacığının bir seferde python kodunu yorumlayabileceği anlamına gelir, iş parçacığı yönetimi ve kaynak tahsisinin çalışmadığı anlamına gelmez.
Benproductions

2
^ böylece herhangi bir zamanda, istemciye yalnızca bir iş parçacığı içerik sunacaktır ... bu nedenle, performansı artırmak için gerçekten çok iş parçacığı kullanmanın anlamı yoktur. sağ?
avi

Ve tabii ki, Java bayt koduna göre derlenmiştir ve çok ince taneli kilitlemeye izin verir.
Warren Çiğ

3
@avi, bir web sunucusu gibi IO'ya bağlı bir işlem hala Python iş parçacıklarından kazanabilir. İki veya daha fazla iş parçacığı aynı anda IO yapabilir. Aynı anda yorumlanamazlar (CPU).
Saish

33

Aşağıdakiler, resmi Python / C API Referans Kılavuzundan alınmıştır :

Python yorumlayıcısı tam olarak iş parçacığı güvenli değildir. Çok iş parçacıklı Python programlarını desteklemek için, Python nesnelerine güvenli bir şekilde erişmeden önce mevcut iş parçacığı tarafından tutulması gereken global bir kilit vardır. Kilit olmadan, en basit işlemler bile çok iş parçacıklı bir programda sorunlara neden olabilir: örneğin, iki iş parçacığı aynı nesnenin referans sayısını aynı anda artırdığında, referans sayısı iki yerine yalnızca bir kez artırılabilir.

Bu nedenle, kural, yalnızca global yorumlayıcı kilidini alan iş parçacığının Python nesneleri üzerinde çalışabileceği veya Python / C API işlevlerini çağırabileceği şeklinde mevcuttur. Çok iş parçacıklı Python programlarını desteklemek için, yorumlayıcı kilidi düzenli olarak serbest bırakır ve yeniden alır - varsayılan olarak, her 100 bayt kodu talimatını (bu sys.setcheckinterval () ile değiştirilebilir). Kilit ayrıca, bir dosyayı okumak veya yazmak gibi potansiyel olarak engelleyici G / Ç işlemleri etrafında serbest bırakılır ve yeniden elde edilir, böylece G / Ç'yi isteyen iş parçacığı G / Ç işleminin tamamlanmasını beklerken diğer iş parçacıkları çalışabilir.

Sanırım sorunu oldukça iyi özetliyor.


1
Ben de okudum, ancak Python'un bu bakımdan neden java'dan farklı olduğunu anlayamıyorum (öyle mi?)
Federico A.Ramponi

@EliBendersky Python konuları pthreads olarak uygulanır ve işletim sistemi tarafından yönetilir ( dabeaz.com/python/UnderstandingGIL.pdf ), Java iş parçacıkları ise zamanlama JVM tarafından işlenen uygulama düzeyinde iş parçacıklarıdır
gokul_uf

19

Global yorumlayıcı kilidi, referans sayaçlarının ıslanmasını önleyen büyük bir muteks tipi kilittir. Saf python kodu yazıyorsanız, bunların hepsi perde arkasında gerçekleşir, ancak Python'u C'ye yerleştirirseniz, kilidi açıkça almanız / bırakmanız gerekebilir.

Bu mekanizma, Python'un bayt koduna derlenmesiyle ilgili değildir. Java için gerekli değildir. Aslında, Jython için bile gerekli değildir (python, jvm'ye derlenmiştir).

ayrıca bu soruya bakın


4
"Bu mekanizma Python'un bayt kodu ile derlenmesi ile ilgili değildir": Kesinlikle, CPython uygulamasının bir ürünüdür. Diğer uygulamalar (bahsettiğiniz Jython gibi) iş parçacığı güvenli uygulamaları sayesinde bu kısıtlamadan muaf olabilir
Eli Bendersky

11

Python, perl 5 gibi, sıfırdan iş parçacığı için güvenli olacak şekilde tasarlanmamıştır. İplikler olaydan sonra aşılandı, bu nedenle küresel yorumlayıcı kilidi, yorumlayıcının bağırsaklarında belirli bir zamanda yalnızca bir iş parçacığının kod yürüttüğü yerde karşılıklı dışlamayı sağlamak için kullanılır.

Bireysel Python iş parçacıkları, kilidin sık sık çevrilmesiyle tercümanın kendisi tarafından işbirliği içinde çoklu görev gerçekleştirir.

Diğer Python iş parçacıkları bu protokole 'katılmak' için aktifken ve arkanızda güvensiz hiçbir şeyin olmadığından emin olmak için C'den Python ile konuşurken kilidi kendiniz almanız gerekir.

Daha sonra çok iş parçacıklı sistemlere dönüşen tek iş parçacıklı bir mirasa sahip diğer sistemler, genellikle bu türden bir mekanizmaya sahiptir. Örneğin, Linux çekirdeği SMP'nin ilk günlerinden itibaren "Büyük Çekirdek Kilidi" ne sahiptir. Zaman içinde kademeli olarak, çoklu iş parçacığı performansı bir sorun haline geldikçe, bu tür kilitleri daha küçük parçalara ayırmaya veya mümkün olan yerlerde verimliliği en üst düzeye çıkarmak için kilitsiz algoritmalar ve veri yapılarıyla değiştirmeye çalışma eğilimi vardır.


+1, kaba taneli kilitlemenin çoğu kişinin düşündüğünden, özellikle de sık sık unutulan BKL (kullanıyorum reiserfs- bunu bildiğim tek gerçek neden) kullanıldığından bahsettiği için .
new123456

3
Linux 2.6.39 sürümünden beri BKL'ye sahipti, BKL tamamen kaldırıldı.
avi

5
Elbette. Unutmayın, soruyu cevapladıktan ~ 3 yıl sonraydı. =)
Edward KMETT

7

İkinci sorunuzla ilgili olarak, tüm komut dosyası dilleri bunu kullanmaz, ancak yalnızca onları daha az güçlü hale getirir. Örneğin, Ruby'deki diziler yeşildir ve yerel değildir.

Python'da, iş parçacıkları yereldir ve GIL yalnızca bunların farklı çekirdekler üzerinde çalışmasını engeller.

Perl'de iplikler daha da kötü. Tüm yorumlayıcıyı kopyalarlar ve Python'daki kadar kullanılabilir olmaktan uzaktırlar.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.