Javac gibi derleyiciler saf işlevleri otomatik olarak algılar ve paralel hale getirir mi?


12

Saf fonksiyonların parellelleştirmeyi kolaylaştırdığı bilinmektedir. Doğrusal olarak paralel yürütmeye uyum sağlayan işlevsel programlama hakkında ne var?

Javac gibi derleyiciler, bir yöntemin saf bir işlev olduğunu algılayacak kadar akıllı mıdır? Her zaman Fonksiyon gibi fonksiyonel arayüzler uygulayan ancak yan etkileri olan sınıflar uygulanabilir .


7
Soru sadece derleyicinin bir fonksiyonun saf olup olmadığını bilip bilmeyeceği değil, aynı zamanda saf fonksiyonların paralel yürütülmesini akıllıca planlayıp programlayamayacağıdır. Her biri için yeni bir iplik açmak yeterli değildir: bu verimsizdir. GHC (Haskell) bunu tembellik ve "yeşil iplikler" kullanarak ele alır; Saf ipliklerin ana saf olmayan iplikle ilgili olarak doğru bir şekilde planlandığından emin olmanın ek zorluğu göz önüne alındığında, herhangi bir safsızlık dili denendiyse dürüstçe şaşırırdım.
Ryan Reich

@RyanReich, Java gibi saf olmayan bir işlevsel dilde işlevsel programlama kullanmanın herhangi bir performans kazancı var mı? gibi fonksiyonel programlamanın kazanımları tamamen işlevsel midir?
Naveen

@RyanReich GHC problemle, programcının paralellik istediklerinde açıklama eklemesini sağlar. Saflık, bu ek açıklamaların hiçbir zaman anlambilimi değiştirmediğini, sadece performansı değiştirdiğini ima eder. (Paralelliğe yol açabilecek eşzamanlılık mekanizmaları da vardır, ancak bu farklı bir balık su ısıtıcısıdır.)
Derek Elkins SE

@Naveen Saf fonksiyonların optimizasyon açısından, daha fazla serbestlik kodu yeniden sıralaması, not alma ve ortak alt ifade kaldırması gibi paralelliğin yanı sıra başka faydaları da vardır. Yanlış olabilirim, ama javac'ın saflığı tespit etmeye çalıştığından şüpheliyim, çünkü muhtemelen deyimsel kodda oldukça nadir ve en önemsiz durumlar hariç herkes için biraz zor. Örneğin, herhangi bir NullPointerExceptions olmayacağını bilmeniz gerekir . Buna dayalı optimizasyonların faydaları, tipik Java uygulamaları için de oldukça küçüktür.
Derek Elkins SE

6
javac, java kaynak kodunu alan ve java bayt kodu sınıf dosyaları üreten java derleyicisidir. Ne yapabileceği (ve yapması gerektiği) konusunda oldukça kısıtlıdır. Bayt kodu sınıf dosyasına paralellik kazandırmak için gerekli temel mekanizma veya gerekli mekanizma yoktur.
Erik Eidt

Yanıtlar:


33

Javac smart gibi bir yöntemin saf bir işlev olduğunu algılayacak kadar derleyicidir.

"Yeterince akıllı" sorunu değil. Buna Saflık Analizi denir ve genel durumda imkansızdır: Durdurma Problemini çözmeye eşdeğerdir.

Şimdi, elbette, optimize ediciler her zaman makul bir şekilde imkansız şeyler yapıyorlar, "genel durumda muhtemelen imkansız" hiçbir zaman çalışmadığı anlamına gelmiyor, sadece her durumda çalışamayacağı anlamına geliyor. Yani, aslında bir fonksiyonun saf olup olmadığını kontrol etmek için algoritmalar vardır, sonuçtan daha sık "Bilmiyorum" olacaktır, yani güvenlik ve doğruluk nedenleriyle, bu özel işlev saf olmayabilir.

Ve işe yaradığı durumlarda bile , algoritmalar karmaşık ve pahalıdır.

Yani, bu Sorun # 1: sadece özel durumlar için çalışıyor .

Sorun # 2: Kütüphaneler . Bir fonksiyonun saf olması için, sadece saf fonksiyonları çağırabilir (ve bu fonksiyonlar sadece saf fonksiyonları çağırabilir, vb.). Javac açıkçası sadece Java'yı biliyor ve sadece görebileceği kodu biliyor. Bu nedenle, işleviniz başka bir derleme birimindeki bir işlevi çağırırsa, bunun saf olup olmadığını bilemezsiniz. Başka bir dilde yazılmış bir işlevi çağırırsa, bilemezsiniz. Kütüphanede henüz yüklenmemiş bir işlevi çağırırsa, bilemezsiniz. Ve bunun gibi.

Bu, tüm program analiziniz olduğunda, tüm program aynı dilde yazıldığında ve hepsi bir seferde bir kerede derlendiğinde çalışır. Hiçbir kitaplığı kullanamazsınız.

Sorun # 3: Zamanlama . Hangi parçaların saf olduğunu anladıktan sonra, bunları yine de dişleri ayırmak için zamanlamanız gerekir. Ya da değil. İş parçacıklarını başlatmak ve durdurmak çok pahalıdır (özellikle Java'da). Bir iş parçacığı havuzu tutup başlatmamanız veya durdurmasanız bile, iş parçacığı bağlamı geçişi de pahalıdır. Hesaplamanın zamanlama ve bağlam değiştirme için gereken süreden önemli ölçüde daha uzun çalışacağından emin olmanız gerekir, aksi takdirde performansı kaybetmezsiniz , kazanmazsınız.

Muhtemelen şimdiye kadar tahmin ettiğiniz gibi, bir hesaplamanın ne kadar süreceğini anlamak genel durumda imkansızdır (hatta ne kadar zaman geçse de, sınırlı bir zaman alıp almayacağını bile anlayamayız) ve hatta zor ve pahalı özel durum.

Bir yana: Javac ve optimizasyonlar . Javac uygulamalarının çoğunun aslında pek çok optimizasyon yapmadığını unutmayın. Örneğin Oracle'ın javac uygulaması, optimizasyon yapmak için temel yürütme motoruna dayanır . Bu, başka bir sorun kümesine yol açar: diyelim ki, javac belirli bir işlevin saf ve yeterince pahalı olduğuna karar verdi ve bu yüzden farklı bir iş parçacığında yürütülmesini derledi. Ardından, platformun iyileştiricisi (örneğin, HotSpot C2 JIT derleyicisi) birlikte gelir ve tüm işlevi ortadan kaldırır. Artık boş bir iş parçacığınız yok. Ya da, hayal, yine Javac farklı bir iş parçacığı üzerinde bir işlevi zamanlama karar verir ve platform iyileştirici olabilir iplik sınırları boyunca satır içi işlem yapamaması dışında tamamen optimize edin ve böylece tamamen optimize edilebilen bir işlev artık gereksiz yere yürütülmektedir.

Yani, böyle bir şey yapmak sadece bir seferde optimizasyonların çoğunu yapan tek bir derleyiciniz varsa mantıklıdır, böylece derleyici farklı seviyelerdeki tüm farklı optimizasyonları ve birbirleriyle etkileşimlerini bilir ve bunlardan yararlanabilir.

Not örneğin HotSpot C2 JIT derleyicisi aslında yapar oto-paralelleştirme şeklidir bir otomatik vektörelleştirmeyi gerçekleştirmek.


Peki, "saf fonksiyon" tanımınıza bağlı olarak, uygulamada saf olmayan fonksiyonların kullanılmasına izin verilebilir.
Deduplicator

@Deduplicator Eh, tanımına bağlı definitionbir farklı kullanarak, definitionbir purityolasılıkla belirsizliğini
kedi

1
Sorun # 2 çoğunlukla hemen hemen tüm optimizasyonların JIT tarafından yürütülmesi ile geçersiz kılınmıştır (bunu açıkça biliyorsunuz, ama görmezden geliyorsunuz). Benzer şekilde JIT, büyük ölçüde tercüman tarafından toplanan istatistiklere dayandığı için sorun # 3 kısmen geçersiz hale gelir. Kurtarmaya deoptimizasyon olduğu için özellikle "Kütüphane kullanamazsınız" konusuna katılmıyorum. Eklenen karmaşıklığın bir sorun olacağına katılıyorum.
maaartinus

2
@maaartinus: Ayrıca, cevabımın sadece sonu javac'a özgü. Özellikle do "Bu yalnızca çalışır, tüm programı aynı dilde yazılmış ve tüm tek seferde seferde derlenen tam program analizi, varken." Diye, örneğin, söz Bu açıkça C2 için geçerlidir: sadece bir dil (JVM bayt kodu) ile ilgilenir ve tüm programa aynı anda erişebilir.
Jörg W Mittag

1
@ JörgWMittag OP'nin javac'ı sorduğunu biliyorum, ama javac'ın optimizasyonlardan sorumlu olduğunu varsayarlar. Ve C2 olduğunu pek bilmiyorlar. Söylemiyorum, cevabınız kötü. Sadece javac'ın (kullanma gibi önemsizlikler hariç) herhangi bir optimizasyon yapmasına izin vermek StringBuilderbir anlamsızdır, bu yüzden onu reddeder ve basitçe varsayarız, OP javac yazar ancak Hotspot anlamına gelir. Sorun # 2, Javac'ta herhangi bir şeyi optimize etmenize karşı oldukça iyi bir neden .
maaartinus

5

Yükseltilmiş cevap bir şeyi not edemedi. Dişler arasındaki senkron iletişim son derece pahalıdır. İşlev saniyede milyonlarca çağrı hızında yürütülebiliyorsa, aslında olduğu gibi bırakmak yerine onu paralel hale getirmek için daha fazla acı verir.

Atomik değişkenlerle meşgul döngüler kullanan en hızlı senkron inter-thread iletişim biçimi maalesef enerji verimsizdir. Enerji tasarrufu için koşul değişkenlerini kullanmaya başvurmanız gerekiyorsa, zincirler arası iletişiminizin performansı düşer.

Bu nedenle, derleyici sadece bir fonksiyonun saf olup olmadığını belirlemekle kalmaz, aynı zamanda paralelleştirmenin net bir kazanç olup olmadığını görmek için fonksiyonun yürütme süresini tahmin etmelidir. Ayrıca, atomik değişkenler veya koşul değişkenleri kullanan meşgul döngüler arasında seçim yapmak gerekir. Ve arkanızda iplikler oluşturmanız gerekir.

İş parçacıklarını dinamik olarak oluşturursanız, koşul değişkenlerini kullanmaktan bile daha yavaştır. Bu nedenle, derleyicinin zaten çalışmakta olan belirli sayıda iş parçacığı ayarlaması gerekir.

Yani, sorunuzun cevabı hayır , derleyiciler özellikle Java dünyasında saf fonksiyonları otomatik olarak paralelleştirecek kadar "akıllı" değiller. Onları otomatik olarak paralelleştirerek akıllıdırlar!


5
" Onları otomatik olarak paralelleştirmekten zekiler! " : Bu çok ileri gidiyor. Sadece kendi uğruna mümkün olan her noktada paralelleştirmenin genellikle verimsiz olacağı doğru olsa da, akıllı bir derleyici pratik bir paralelleştirme stratejisi belirleyecektir. Çoğu insanın bunu anladığını düşünüyorum, bu yüzden otomatik paralelleştirme hakkında konuştuğumuzda, otomatik pratik-paralelleştirme demek istiyoruz.
Nat

@Nat: Gülünç çok zor. Bu, 100'lerin milisaniyelik çalışma zamanı ölçeğinde saf işlevlerin tanımlanmasını ve derleyicinin yinelemelerinde sabit olmayan döngülerin çalışma zamanı hakkında herhangi bir fikir almasını beklemek (ve istemediğiniz durumlar) saçmadır.
Joshua

Kabul ediyorum - @ Nat'ın yorumu, paralelleştirmenin mutlaka birden fazla iş parçacığı anlamına gelmediğini ima eder, bu doğrudur. Örneğin, JIT, saf bir işleve birden çok çağrı gönderebilir ve bazı durumlarda CPU talimatlarını araya ekleyebilir. Örneğin, her iki yöntem çağrısı da sabit getiriliyorsa, bir kez getirilebilir ve kullanılacak yöntemin her iki örneği için bir CPU kaydında tutulabilir. Modern CPU'lar çok sayıda genel amaçlı kayıtlara ve kodu optimize ederken oldukça yardımcı olabilecek özel talimatlara sahip hayvanlardır.

1
@Joshua: Bir JIT derleyicisi için gerçekten çok daha kolay. JIT derleyicisi ayrıca bir işlevin saf olmayabileceğini, ancak şu ana kadar hiçbir çağrının saf olmayan davranışa yol açmayacağını anlayabilir.
gnasher729

@Joshua'ya katılıyorum. İş yerinde paralelleştirilmesi zor bir algoritmam var. Bazı basitleştirici yaklaşımlar yaparak (ve böylece algoritmayı değiştirerek) bile manuel olarak paralelleştirmeye çalıştım ve her seferinde sefil bir şekilde başarısız oldum. Bir şeyi paralelleştirmenin mümkün olup olmadığını söyleyen bir program bile, aslında paralelleştirmekten çok daha basit olsa da, son derece zordur. Turing-complete programlama dillerinden bahsettiğimizi unutmayın.
juhist
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.