Tại sao Raku hoạt động rất tệ với các mảng đa chiều?


10

Tôi tò mò tại sao Raku thực hiện quá tệ thao túng các mảng đa chiều. Tôi đã thực hiện một thử nghiệm nhanh khi khởi tạo ma trận 2 chiều trong Python, C # và Raku và thời gian trôi qua cao đáng ngạc nhiên cho lần sau.

Dành cho Raku

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

Đối với Python

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

Tôi đang làm sai à? Có vẻ như quá nhiều sự khác biệt.


5
Nó chỉ chậm đối với các mảng đa chiều có hình dạng (một trong những nơi bạn xác định nó @grid[4000;4000]) mã python không sử dụng một mảng có hình dạng và bạn thử tương tự trong Raku, bạn sẽ có được thời gian tốt hơn nhiều: my @grid = [[0 xx 4000] xx 4000]; Điều đó có nghĩa là bạn phải truy cập @grid[0][0]không @grid[0;0]. Tôi nghĩ rằng điều này chủ yếu là vì các mảng hình vẫn là một công việc đang tiến triển.
Scimon Proctor

1
Trên máy tôi @grid[1000;1000] = [[0 xx 1000]xx1000]mất 12 giây. @grid = [[0 xx 1000]xx1000]mất 0,6 nên ... ừ. Tôi sẽ tránh các mảng hình.
Scimon Proctor

5
@Scimon bạn thực sự vẫn có thể sử dụng trình truy cập [;] cho các mảng không bị che chắn. my @grid = [[$++ xx 100] xx 100]; say @grid[0;1]; say @grid[1;1]trả về lần lượt 1 và 101
user0721090601

Tuyệt vời! Điều đó làm cho mọi thứ dễ dàng hơn.
Scimon Proctor

2
Các mảng đa chiều có hình dạng chưa nhận được sự tốt đẹp tối ưu hóa mà nhiều khu vực khác của Rakudo đã nhận được.
Elizabeth Mattijsen

Câu trả lời:


13

Một so sánh trực tiếp ban đầu

Tôi sẽ bắt đầu với mã được liên kết chặt chẽ hơn nhiều với mã Python của bạn so với bản dịch của riêng bạn. Tôi nghĩ mã Raku tương đương trực tiếp với Python của bạn là:

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

Mã này khai báo một định danh không có sigil 1 . Nó:

  • Giọt "định hình" ( [4000;4000]trong my @table[4000;4000]). Tôi đã bỏ nó vì mã Python của bạn không làm điều đó. Định hình lợi thế nhưng có ý nghĩa hiệu suất. 2

  • Sử dụng ràng buộc thay vì chuyển nhượng . Tôi chuyển sang ràng buộc vì mã Python của bạn đang thực hiện ràng buộc chứ không phải gán. (Python không phân biệt giữa hai loại.) Trong khi phương pháp phân công của Raku mang lại những lợi thế cơ bản đáng có cho mã chung, nó có ý nghĩa về hiệu năng. 3


Mã này tôi đã bắt đầu câu trả lời của tôi vẫn còn chậm.

Đầu tiên, mã Raku, chạy qua trình biên dịch Rakudo từ tháng 12 năm 2018, chậm hơn khoảng 5 lần so với mã Python của bạn, sử dụng trình thông dịch Python từ tháng 6 năm 2019, trên cùng một phần cứng. 3

Thứ hai, cả mã Raku và mã Python đều chậm, ví dụ so với mã C # của bạn. Chúng ta có thể làm tốt hơn...

Một thay thế thành ngữ nhanh hơn hàng ngàn lần

Các mã sau đây đáng để xem xét:

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

Mặc dù mã này tương ứng với mảng 10 tỷ phần tử đáng chú ý thay vì chỉ 16 triệu phần tử một trong mã Python và C # của bạn, thời gian chạy để chạy nó ít hơn một nửa so với mã Python và chỉ chậm hơn 5 lần so với C # mã. Điều đó cho thấy Rakudo đang chạy mã Raku nhanh hơn hàng nghìn lần so với mã Python tương đương và nhanh gấp hàng trăm lần so với mã C #.

Mã Raku dường như nhanh hơn rất nhiều vì bảng đang được khởi tạo một cách lười biếng bằng cách sử dụng xx Inf. 4 Công việc quan trọng duy nhất được thực hiện khi chạy saydòng. Điều này gây ra việc tạo ra 100.000 mảng thứ nguyên đầu tiên, và sau đó chỉ tạo ra mảng thứ nguyên thứ 100.000 với 100.000 phần tử, để saycó thể hiển thị các phần tử 0được giữ trong phần tử cuối cùng của mảng đó.

Có nhiều hơn một cách để làm điều đó

Một vấn đề tiềm ẩn trong câu hỏi của bạn là luôn có nhiều cách để làm điều đó. 5 Nếu bạn gặp hiệu năng kém đối với mã trong đó tốc độ là quan trọng, thì mã hóa khác đi, như tôi đã làm, có thể tạo ra sự khác biệt lớn. 6

(Một lựa chọn thực sự tốt khác là đặt câu hỏi SO ...)

Tương lai

Raku được thiết kế cẩn thận để được đánh giá cao optimization thể , tức là có thể đến một ngày nào đó chạy nhanh hơn nhiều cho công việc biên dịch đầy đủ trong những năm tới , so với, nói, Perl 5 hoặc Python 3 lon, về mặt lý thuyết, bao giờ chạy, trừ khi họ đi qua một ngầm thiết kế lại và nhiều năm làm việc biên dịch tương ứng.

Một sự tương tự khá ổn là những gì đã xảy ra với hiệu suất của Java trong 25 năm qua. Rakudo / NQP / MoarVM là khoảng một nửa trong quá trình trưởng thành mà ngăn xếp Java đã trải qua.

Chú thích

1 tôi có thể đã viết my $table := .... Nhưng các tuyên bố về hình thức my \foo ...loại bỏ việc xem xét các sigils và cho phép sử dụng =chứ không phải :=là yêu cầu với một định danh sigil'd. (Như một phần thưởng, "cắt xén sigil" dẫn đến một mã định danh không có sigil, quen thuộc với các lập trình viên trong nhiều ngôn ngữ không sử dụng sigils, tất nhiên bao gồm Python và C #.)

2 Việc định hình một ngày nào đó có thể dẫn đến các hoạt động mảng nhanh hơn cho một số mã. Trong khi đó, như đã đề cập trong các bình luận về câu hỏi của bạn, rõ ràng hiện tại nó ngược lại, làm chậm đáng kể nó. Tôi tưởng tượng đó là phần lớn bởi vì mọi truy cập mảng đang bị kiểm tra một cách ngây thơ một cách tự nhiên vào lúc này, dần dần mọi thứ đều ổn, và cũng không có nỗ lực sử dụng kích thước cố định để giúp tăng tốc mọi thứ. Ngoài ra, khi tôi cố gắng đưa ra cách giải quyết nhanh cho mã của bạn, tôi đã không tìm thấy một mảng sử dụng mảng kích thước cố định do nhiều thao tác trên mảng kích thước cố định hiện chưa được thực hiện. Một lần nữa, những điều này hy vọng sẽ được thực hiện vào một ngày nào đó nhưng có lẽ không phải là một điểm đau đủ cho bất cứ ai làm việc để thực hiện chúng cho đến nay.

3 Tại thời điểm viết bài này, TIO đang sử dụng Python 3.7.4, từ tháng 6 năm 2019 và Rakudo v2018.12, từ tháng 12 năm 2018. Hiệu suất của Rakudo hiện đang cải thiện nhanh hơn đáng kể so với trình thông dịch Python 3 chính thức, vì vậy tôi sẽ mong đợi khoảng cách giữa Rakudo mới nhất và Python mới nhất, khi Rakudo chậm hơn, sẽ hẹp hơn đáng kể so với câu trả lời trong câu trả lời này. Đặc biệt, công việc hiện tại đang cải thiện đáng kể hiệu suất của các bài tập.

4 xx mặc định để xử lý lười biếng nhưng một số biểu thức buộc phải đánh giá háo hức do ngữ nghĩa ngôn ngữ hoặc giới hạn trình biên dịch hiện tại. Vào năm v2018.12 cũ, Rakudo, vì một biểu hiện của hình thức [ [ foo xx bar ] xx baz ]vẫn lười biếng và không bị buộc phải đánh giá một cách háo hức, cả hai barbazphải Inf. Ngược lại, my \table = [0 xx 100_000 for ^100_000]lười biếng không sử dụng Inf. (Mã sau thực sự đang lưu trữ 100.000 Seqgiây ở chiều thứ nhất chứ không phải 100.000 Arraygiây - say WHAT table[0]hiển thị Seqchứ không phải Array- nhưng hầu hết mã sẽ không thể phát hiện ra sự khác biệt - say table[99_999;99_999]vẫn sẽ hiển thị 0.)

5 Một số người cho rằng đó là một điểm yếu để chấp nhận rằng có nhiều hơn một cách để suy nghĩ và giải pháp mã cho các vấn đề được đưa ra. Trong thực tế, đó là một thế mạnh trong ít nhất ba liên quan. Đầu tiên, nói chung, bất kỳ vấn đề không tầm thường nào cũng có thể được giải quyết bằng nhiều thuật toán riêng biệt với sự khác biệt lớn trong hồ sơ hiệu suất. Câu trả lời này bao gồm một cách tiếp cận đã có sẵn với Rakudo một năm tuổi sẽ nhanh hơn một nghìn lần so với Python trong thực tế trong một số tình huống. Thứ hai, một ngôn ngữ đa mô hình có chủ ý và linh hoạt như Raku cho phép một lập trình viên (hoặc nhóm lập trình viên) thể hiện một giải pháp mà họ cho là thanh lịch và có thể duy trì được, hoặc chỉ cần hoàn thành công việc, dựa trên những gì họ làmnghĩ là tốt nhất, không phải những gì ngôn ngữ áp đặt. Thứ ba, hiệu suất của Rakudo như một trình biên dịch tối ưu hóa hiện đang thay đổi đáng chú ý. May mắn thay, nó có một hồ sơ tuyệt vời 6 , vì vậy người ta có thể thấy nút thắt ở đâu và tính linh hoạt cao, vì vậy người ta có thể thử mã hóa thay thế và điều này có thể tạo ra mã nhanh hơn rất nhiều.

6 Khi vấn đề về hiệu suất hoặc nếu bạn đang điều tra các vấn đề về hiệu suất, hãy tham khảo trang tài liệu Raku về hiệu suất ; trang này bao gồm một loạt các tùy chọn bao gồm cả việc sử dụng trình hồ sơ Rakudo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.