Raku neden çok boyutlu dizilerde bu kadar kötü performans gösteriyor?


10

Raku'nun neden çok boyutlu dizileri manipüle etmekte bu kadar kötü performans gösterdiğini merak ediyorum. Python, C # ve Raku'da 2 boyutlu bir matris başlatan hızlı bir test yaptım ve geçen süre daha sonra için şaşırtıcı derecede yüksek.

Raku için

my @grid[4000;4000] = [[0 xx 4000] xx 4000];
# Elapsed time 42 seconds !!

Python için

table= [ [ 0 for i in range(4000) ] for j in range(4000) ]
# Elapsed time 0.51 seconds

C #

int [,]matrix = new int[4000,4000];
//Just for mimic same behaviour
for(int i=0;i<4000;i++)
   for(int j=0;j<4000;j++)
       matrix[i,j] = 0;
# Elapsed time 0.096 seconds

Yanlış mı yapıyorum? Çok fazla fark gibi görünüyor.


5
O (En tanımlamak EG tek şekilli çok boyutlu diziler için sadece yavaş @grid[4000;4000]piton kodu çok daha iyi bir zaman geri almak Raku aynı deneyin bir şekilli dizi kullanarak ve senin değildir): my @grid = [[0 xx 4000] xx 4000]; Onunla birlikte erişime gerek demek @grid[0][0]değil @grid[0;0]. Bence bu çoğunlukla şekillendirilmiş dizilerin hala devam eden bir çalışma olması.
Scimon Proctor

1
Benim makinede @grid[1000;1000] = [[0 xx 1000]xx1000]12 saniye sürdü. @grid = [[0 xx 1000]xx1000]0,6 aldı ... evet. Şekilli dizilerden kaçınırdım.
Scimon Proctor

5
@Scimon, şekilli diziler için [;] erişimciyi kullanmaya devam edebilirsiniz. my @grid = [[$++ xx 100] xx 100]; say @grid[0;1]; say @grid[1;1]sırasıyla 1 ve 101
değerini

Müthiş! Bu işleri kolaylaştırır.
Scimon Proctor

2
Şekilli çok boyutlu diziler henüz Rakudo'nun diğer birçok alanının aldığı optimizasyon iyiliğini almadı.
Elizabeth Mattijsen

Yanıtlar:


13

İlk doğrudan karşılaştırma

Python kodunuzla kendi çevirinizden çok daha uyumlu bir kodla başlayacağım. Ben düşünüyorum Python olduğu için en doğrudan eşdeğer Raku kodu:

my \table = [ [ 0 for ^4000 ] for ^4000 ];
say table[3999;3999]; # 0

Bu kod, sigil içermeyen bir tanımlayıcı 1 bildirir . O:

  • "Şekillendirme" ( [4000;4000]in my @table[4000;4000]) bırakır . Düşürdüm çünkü Python kodunuz bunu yapmıyor. Şekillendirme avantajlar sağlar, ancak performans sonuçları vardır. 2

  • Atama yerine ciltleme kullanır . Bağlanmaya geçtim çünkü Python kodunuz atama değil bağlanma yapıyor. (Python ikisi arasında ayrım yapmaz.) Raku'nun görevlendirme yaklaşımı, genel kod için sahip olmaya değer temel avantajlar getirse de, performans sonuçları vardır. 3


Cevabımı başlattığım bu kod hala yavaş.

İlk olarak, Aralık 2018'den itibaren bir Rakudo derleyicisi aracılığıyla çalıştırılan Raku kodu, aynı donanımda Haziran 2019'dan bir Python yorumlayıcısı kullanarak Python kodunuzdan yaklaşık 5 kat daha yavaştır. 3

İkincisi, hem Raku kodu hem de Python kodu yavaştır, örneğin C # kodunuzla karşılaştırıldığında. Daha iyisini yapabiliriz ...

Bin kat daha hızlı deyimsel bir alternatif

Aşağıdaki kod dikkate değer:

my \table = [ [ 0 xx Inf ] xx Inf ];
say table[ 100_000; 100_000 ]; # 0

Python ve C # kodunuzdaki 16 milyon elemandan ziyade kavramsal bir 10 milyar eleman dizisine karşılık gelen bu koda rağmen , onu çalıştırmak için wallclock süresi Python kodunun yarısından daha az ve C # 'dan sadece 5 kat daha yavaş kodu. Rakudo'nun Raku kodunu eşdeğer Python kodundan bin kat ve C # kodundan yüz kat daha hızlı çalıştırdığını gösterir.

Raku kodu çok daha hızlı görünüyor, çünkü tablo tembel olarak kullanılarak başlatılıyor xx Inf. 4 Tek önemli çalışma sayhattın yürütülmesi ile ilgilidir . 100.000 ilk boyut dizinin bu nedenler oluşturulması ve daha sonra bu yüzden, 100.000 elemanları sadece 100.000 ikinci boyut dizisi doldurma saygörüntüleyebilir 0bu dizinin en son elemanının içinde tutulur.

Bunu Yapmanın Birden Fazla Yolu Var

Sorunuzun altında yatan bir sorun, her zaman bunu yapmanın birden fazla yolu olmasıdır. 5 Hızın kritik olduğu kod için düşük performansla karşılaşırsanız, yaptığım gibi farklı kodlama yapmak dramatik bir fark yaratabilir. 6

(Bir başka gerçekten iyi seçenek SO sorusu sormaktır ...)

Gelecek

Raku dikkatle yüksek optimiz olacak şekilde tasarlanmıştır mümkün , yani mümkün için bir gün çalıştırmak çok daha hızlı verilen önümüzdeki yıllarda yeterli derleyici çalışmaları bir çığır geçmesi sürece, 3 kutu, teoride, şimdiye kadar koşmak, diyelim ki, daha, Perl 5 veya Python yeniden tasarım ve yıllarca ilgili derleyici çalışması.

Java'nın son 25 yıldaki performansında olan şey biraz iyi bir benzetme. Rakudo / NQP / MoarVM, Java yığınının geçtiği olgunlaşma sürecinin yaklaşık yarısındadır.

Dipnotlar

1 Yazabilirdim my $table := .... Ancak formun beyanları, imzaların my \foo ...değerlendirilmesini ortadan kaldırır ve bir sigil'd tanımlayıcı ile =gerekenden ziyade kullanılmasına izin verir :=. (Bonus olarak, "sigil'i kesmek", elbette Python ve C # içeren sigils kullanmayan birçok dilde kodlayıcılara aşina olan sigil içermeyen bir tanımlayıcıyla sonuçlanır.)

2 Şekillendirme bir gün bazı kodlar için daha hızlı dizi işlemlerine neden olabilir. Bu arada, sorunuzun yorumlarında belirtildiği gibi, şu anda açıkça tersini yapıyor ve önemli ölçüde yavaşlatıyor. Her dizi erişim safça olduğu için durduruldu büyük ölçüde budur hayal dinamik andan yavaş her şey aşağı at sınırlarla denetlenir ve ayrıca yardım hız süslemeye sabit boyutu kullanmak için hiçbir çaba oldu. Ayrıca, kodunuz için hızlı bir geçici çözüm bulmaya çalıştığımda, şu anda uygulanmayan sabit boyutlu diziler üzerindeki birçok işlem nedeniyle sabit boyutlu diziyi kullanarak bir tane bulamadım. Yine, bunlar umarım bir gün uygulanacaktır, ancak muhtemelen bugüne kadar bunları uygulamak için kimsenin çalışması için yeterli bir ağrı noktası olmamıştır.

3 Bunu yazarken, TIO Haziran 2019'dan Python 3.7.4 ve Aralık 2018'den Rakudo v2018.12 kullanıyor. Rakudo'nun performansı şu anda resmi Python 3 yorumlayıcısından önemli ölçüde daha hızlı bir şekilde iyileşiyor, bu yüzden Rakudo daha yavaş olduğunda en son Rakudo ve en son Python arasındaki boşluğun bu cevapta belirtilenden önemli ölçüde daha dar olmasını beklemek. Özellikle, mevcut çalışma ödevlerin performansını önemli ölçüde artırmaktadır.

xxTembel işlemenin varsayılanı 4'tür, ancak bazı ifadeler dil anlambilimi veya mevcut derleyici sınırlamaları nedeniyle istekli değerlendirmeyi zorlar. Yaşındaki v2018.12 Rakudo yılında formun bir ifadesi için [ [ foo xx bar ] xx baz ]tembel kalması ve heyecanla değerlendirmek zorunda değil, hem bar ve bazolmalıdır Inf. Aksine, my \table = [0 xx 100_000 for ^100_000]hiçbir faydası ile tembel Inf. (İkinci kod aslında 100.000 Seqs yerine 100.000 Arrays yerine birinci boyutta depolanıyor - say WHAT table[0]ekranlar - Seqyerine Array- ancak çoğu kod farkı fark edemeyecek - say table[99_999;99_999]görüntülenmeye devam edecek 0.)

5 Bazıları , verilen sorunlara çözüm bulmanın ve çözüm bulmanın birden fazla yolu olduğunu kabul etmenin zayıf olduğunu düşünüyor. Gerçekte bu en az üç açıdan bir güçtür . Birincisi, genel olarak, herhangi bir önemsiz olmayan problem, performans profilinde dramatik farklılıklara sahip birçok farklı algoritma ile çözülebilir. Bu cevap, bazı senaryolarda pratikte Python'dan bin kat daha hızlı olacak olan bir yıllık Rakudo ile mevcut olan bir yaklaşımı içerir. İkincisi, Raku gibi kasten esnek ve çok paradigma dil bir kodlayıcı (veya kodlayıcıların takım) bir çözüm ifade etmesini sağlar onlar zarif ve sürdürülebilir düşünün, ya da sadece dayanan, işi alır da ne onlardüşünmek en iyisidir, dilin empoze ettiği şey değildir. Üçüncüsü, Rakudo'nun optimize edici bir derleyici olarak performansı şu anda oldukça değişkendir. Neyse ki harika bir profil 6 vardır , bu yüzden bir darboğazın nerede olduğunu ve büyük esnekliği görebilir, böylece alternatif kodlamayı deneyebilir ve bu çok daha hızlı kod üretebilir.

6 Performans önemli olduğunda veya performans sorunlarını araştırıyorsanız, performans hakkındaki Raku doküman sayfasına bakın ; sayfa, Rakudo profil oluşturucusunun kullanımı dahil bir dizi seçeneği kapsar.

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.