Trải nghiệm lập trình thực đầu tiên của tôi là với Haskell. Đối với các nhu cầu đặc biệt của tôi, tôi yêu cầu một công cụ dễ học, nhanh chóng để viết mã và đơn giản để duy trì và tôi có thể nói nó đã làm công việc độc đáo.C so sánh Haskell Collatz phỏng đoán so sánh tốc độ
Tuy nhiên, tại một thời điểm quy mô nhiệm vụ của tôi trở nên lớn hơn nhiều và tôi nghĩ rằng C có thể phù hợp với họ tốt hơn và nó đã làm. Có lẽ tôi không đủ kỹ năng về lập trình [bất kỳ] nào, nhưng tôi không thể làm cho Haskell có hiệu quả về tốc độ như C, mặc dù tôi nghe nói rằng Haskell thích hợp có khả năng hoạt động tương tự. Gần đây, tôi nghĩ rằng tôi sẽ thử một số Haskell một lần nữa, và trong khi nó vẫn tuyệt vời cho nhiệm vụ đơn giản (về tính toán), nó dường như không thể phù hợp với tốc độ của C với các vấn đề như phỏng đoán Collatz. Tôi đã đọc:
Speed comparison with Project Euler: C vs Python vs Erlang vs Haskell
GHC Optimization: Collatz conjecture
collatz-list implementation using haskell
Nhưng từ những gì tôi nhìn thấy, phương pháp tối ưu hóa đơn giản, bao gồm:
- chọn loại "chặt chẽ", như Int64 thay vì của Integer
- chuyển tối ưu hóa GHC s trên
- sử dụng các kỹ thuật tối ưu hóa đơn giản như tránh tính toán không cần thiết hoặc các chức năng đơn giản
vẫn không làm cho Haskell đang thậm chí gần gần như giống hệt nhau (về mặt phương pháp luận) mã C cho số thực sự lớn. Điều duy nhất dường như làm cho hiệu suất của nó so sánh với C [đối với các vấn đề quy mô lớn] là sử dụng các phương pháp tối ưu làm cho mã trở thành một địa ngục dài, khủng khiếp, đi ngược lại các nguyên tắc mà Haskell (và tôi) đánh giá rất nhiều.
Dưới đây là phiên bản C:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int32_t col(int64_t n);
int main(int argc, char **argv)
{
int64_t n = atoi(argv[1]), i;
int32_t s, max;
for(i = 2, max = 0; i <= n; ++i)
{
s = col(i);
if(s > max) max = s;
}
printf("%d\n", max);
return 0;
}
int32_t col(int64_t n)
{
int32_t s;
for(s = 0; ; ++s)
{
if(n == 1) break;
n = n % 2 ? 3 * n + 1 : n/2;
}
return s;
}
và phiên bản Haskell:
module Main where
import System.Environment (getArgs)
import Data.Int (Int32, Int64)
main :: IO()
main = do
arg <- getArgs
print $ maxCol 0 (read (head arg) :: Int64)
col :: Int64 -> Int32
col x = col' x 0
col' :: Int64 -> Int32 -> Int32
col' 1 n = n
col' x n
| rem x 2 == 0 = col' (quot x 2) (n + 1)
| otherwise = col' (3 * x + 1) (n + 1)
maxCol :: Int32 -> Int64 -> Int32
maxCol maxS 2 = maxS
maxCol maxS n
| s > maxS = maxCol s (n - 1)
| otherwise = maxCol maxS (n - 1)
where s = col n
TL; DR: Là mã Haskell nhanh chóng để viết và đơn giản để duy trì chỉ cho các nhiệm vụ tính toán đơn giản và mất này đặc trưng khi hiệu suất là rất quan trọng?
Tôi chưa bao giờ ngờ rằng GHC không tối ưu hóa phân chia! Và tôi sử dụng Windows GHC 7.4.2, vì vậy tôi đoán đây là vấn đề thứ hai (nó là 32bit). Bạn có thể chỉ cho tôi một số nguồn trên các lỗ hổng GHC như vậy (tôi đoán nó nên được coi là một lỗ hổng)? – ljedrz
@ yzb3 Nâng cấp lên 7.6.1, có phiên bản 64 bit dành cho Windows. Nâng cấp càng nhanh càng tốt. Yeah, GHC là ** Awe-so-me ** theo như sự tối ưu hóa ở mức độ cao, nhưng phần nào lại thiếu ở mức tối ưu thấp. Không đủ người làm việc trên đó và nhu cầu về tiện ích mở rộng ngôn ngữ cao hơn mức tối ưu hóa ở mức độ thấp. Tôi biết không có bộ sưu tập các điểm yếu như vậy, bạn có thể tìm kiếm [trac] (http://hackage.haskell.org/trac/ghc) cho các vé liên quan đến hiệu suất khác nhau, ngoài ra, lời khuyên tốt nhất tôi có thể đưa ra là đọc cốt lõi (và asm, nếu bạn có thể). –
Hãy lưu trữ câu hỏi này để cho thấy rằng các câu hỏi không mang tính xây dựng có thể là chủ đề dạy người dùng điều gì đó rất thú vị. – David