Thứ nhất, nếu bạn đang so sánh hiệu suất cho công cụ số, danh sách không phải là lựa chọn tốt nhất. Hãy thử một gói như gói vector cho các mảng nhanh.
Và lưu ý rằng bạn có thể làm tốt hơn nữa trong Haskell, nhờ vào phản ứng tổng hợp vòng lặp. Bằng cách viết hàm tạo ra như một điều tra, trình biên dịch có thể kết hợp bước tạo và vòng lặp, thành một vòng lặp đơn lẻ mà không phân bổ cấu trúc dữ liệu trung gian. Khả năng kết hợp tổng quát như thế này là duy nhất đối với GHC Haskell.
tôi sẽ sử dụng thư viện vector (stream-based loop fusion):
import qualified Data.Vector as V
test = V.foldl (\ a b -> a + b * sqrt b) 0
create n = (V.enumFromTo 1 n)
main = print (test (create 1000000))
Bây giờ, trước đó, với mã của bạn, trình biên dịch là không thể loại bỏ tất cả các danh sách, và chúng tôi kết thúc với một bên vòng lặp như:
$wlgo :: Double# -> [Double] -> Double#
$wlgo =
\ (ww_sww :: Double#) (w_swy :: [Double]) ->
case w_swy of _ {
[] -> ww_sww;
: x_aoY xs_aoZ ->
case x_aoY of _ { D# x1_aql ->
$wlgo
(+##
ww_sww (*## x1_aql (sqrtDouble# x1_aql)))
xs_aoZ
}
}
$wcreate :: Double# -> [Double]
$wcreate =
\ (ww_swp :: Double#) ->
case ==## ww_swp 0.0 of _ {
False ->
:
@ Double
(D# ww_swp)
($wcreate (-## ww_swp 1.0));
True -> [] @ Double
}
Lưu ý cách có hai vòng: tạo danh sách (lười) và gấp nếp gấp. Nhờ sự lười biếng, chi phí của danh sách đó rẻ, vì vậy nó có giá trị đáng kính:
$ time ./C
4.000004999999896e14
./C 0.06s user 0.00s system 98% cpu 0.058 total
Theo hợp nhất, chúng tôi chỉ nhận được một vòng lặp!
main_$s$wfoldlM_loop :: Double# -> Double# -> Double#
main_$s$wfoldlM_loop =
\ (sc_sYc :: Double#) (sc1_sYd :: Double#) ->
case <=## sc_sYc 1000000.5 of _ {
False -> sc1_sYd;
True ->
main_$s$wfoldlM_loop
(+## sc_sYc 1.0)
(+##
sc1_sYd (*## sc_sYc (sqrtDouble# sc_sYc)))
GHC giảm các bước tạo và thử nghiệm của chúng tôi thành một vòng lặp không có danh sách được sử dụng. Chỉ cần 2 đôi trong sổ đăng ký. Và với một nửa như nhiều vòng, nó chạy gần gấp đôi càng nhanh:
$ ghc D.hs -Odph -fvia-C -optc-O3 -optc-march=native -fexcess-precision --make
$ time ./D
4.000005000001039e14
./D 0.04s user 0.00s system 95% cpu 0.038 total
Đây là một ví dụ tốt đẹp của sức mạnh mà đảm bảo độ tinh khiết cung cấp - trình biên dịch có thể rất hung hăng tại reording mã của bạn.
OCaml có 'lazy' và' Lazy.force'. Nó được sử dụng để thực hiện ML-side rõ ràng mà bất cứ ai có thể viết với một tham chiếu đến một đóng cửa. Hỗ trợ đặc biệt được tích hợp trong thời gian chạy trong 3.0? và nhiều hỗ trợ hơn (mẫu phù hợp) trong 3.11.0. Ngày nay, GC loại bỏ các indirection một thời gian sau khi đình chỉ đã bị buộc. http://ralyx.inria.fr/2008/Raweb/gallium/uid48.html –