Golf này đòi hỏi một tính toán giai thừa được phân chia giữa nhiều luồng hoặc quá trình.
Một số ngôn ngữ làm cho điều này dễ phối hợp hơn những ngôn ngữ khác, vì vậy đó là thuyết bất khả tri. Mã ví dụ được cung cấp, nhưng bạn nên phát triển thuật toán của riêng mình.
Mục tiêu của cuộc thi là để xem ai có thể đưa ra thuật toán nhân tử đa lõi ngắn nhất (tính bằng byte, không phải giây) để tính N! được đo bằng số phiếu khi cuộc thi kết thúc. Cần có một lợi thế đa lõi, vì vậy chúng tôi sẽ yêu cầu nó phải hoạt động với giá trị N ~ 10.000. Các cử tri nên bỏ phiếu nếu tác giả không đưa ra lời giải thích hợp lệ về cách thức phân tán công việc giữa các bộ xử lý / lõi và bỏ phiếu dựa trên sự đồng nhất của golf.
Để tò mò, xin vui lòng gửi một số số hiệu suất. Có thể có một hiệu suất so với đánh đổi điểm golf tại một số điểm, đi với golf miễn là nó đáp ứng các yêu cầu. Tôi tò mò muốn biết khi nào điều này xảy ra.
Bạn có thể sử dụng các thư viện số nguyên lớn lõi đơn có sẵn thông thường. Ví dụ, perl thường được cài đặt với bigint. Tuy nhiên, lưu ý rằng chỉ cần gọi một hệ thống được cung cấp chức năng giai thừa thường sẽ không phân chia công việc trên nhiều lõi.
Bạn phải chấp nhận từ STDIN hoặc ARGV đầu vào N và đầu ra để STDOUT giá trị của N!. Bạn có thể tùy ý sử dụng tham số đầu vào thứ 2 để cung cấp số lượng bộ xử lý / lõi cho chương trình để nó không làm những gì bạn thấy dưới đây :-) Hoặc bạn có thể thiết kế rõ ràng cho 2, 4, bất cứ điều gì bạn có sẵn.
Tôi sẽ đăng ví dụ perl lẻ của riêng tôi bên dưới, trước đây đã được gửi trên Stack Overflow theo Thuật toán nhân tố trong các ngôn ngữ khác nhau . Nó không phải là golf. Vô số ví dụ khác đã được gửi, nhiều người trong số họ chơi golf nhưng nhiều người thì không. Do cấp phép chia sẻ giống nhau, vui lòng sử dụng mã trong bất kỳ ví dụ nào trong liên kết ở trên làm điểm bắt đầu.
Hiệu suất trong ví dụ của tôi là mờ nhạt vì một số lý do: nó sử dụng quá nhiều quá trình, quá nhiều chuyển đổi chuỗi / bigint. Như tôi đã nói đó là một ví dụ kỳ quặc có chủ ý. Nó sẽ tính 5000! trong dưới 10 giây trên máy 4 lõi ở đây. Tuy nhiên, hai lớp lót cho vòng lặp tiếp theo / rõ ràng hơn có thể thực hiện 5000! trên một trong bốn bộ xử lý trong 3.6s.
Bạn chắc chắn sẽ phải làm tốt hơn thế này:
#!/usr/bin/perl -w
use strict;
use bigint;
die "usage: f.perl N (outputs N!)" unless ($ARGV[0] > 1);
print STDOUT &main::rangeProduct(1,$ARGV[0])."\n";
sub main::rangeProduct {
my($l, $h) = @_;
return $l if ($l==$h);
return $l*$h if ($l==($h-1));
# arghhh - multiplying more than 2 numbers at a time is too much work
# find the midpoint and split the work up :-)
my $m = int(($h+$l)/2);
my $pid = open(my $KID, "-|");
if ($pid){ # parent
my $X = &main::rangeProduct($l,$m);
my $Y = <$KID>;
chomp($Y);
close($KID);
die "kid failed" unless defined $Y;
return $X*$Y;
} else {
# kid
print STDOUT &main::rangeProduct($m+1,$h)."\n";
exit(0);
}
}
Quan tâm của tôi về điều này chỉ đơn giản là (1) giảm bớt sự nhàm chán; và (2) học một cái gì đó mới. Đây không phải là một bài tập về nhà hoặc vấn đề nghiên cứu đối với tôi.
Chúc may mắn!