2011-09-13 38 views
8

Xem xét khối mã này:Tại sao sử dụng các hàm được xác định trong cùng một mô-đun nhanh hơn cùng một hàm được xác định trong một mô-đun khác?

isPrime primes' n = foldr (\p r -> p * p > n || (n `rem` p /= 0 && r)) True primes' 

primes = 2 : filter (isPrime primes) [3..] 

main = putStrLn $ show $ sum $ takeWhile (< 1000000) primes 

này sẽ tính tổng của tất cả các số nguyên tố dưới một triệu. Phải mất 0.468 giây để in kết quả trên máy của tôi. Nhưng nếu định nghĩa của isPrimeprimes được trích xuất thành một mô-đun khác, chi phí thời gian là 1.23 giây, tốc độ này gần gấp 3 lần.

Tất nhiên tôi có thể sao chép/dán các định nghĩa ở mọi nơi cần thiết, nhưng tôi cũng tò mò về lý do tại sao điều này xảy ra và cách giải quyết nó.


[Chỉnh sửa] Tôi đang sử dụng GHC 7.0.3 (Windows 7 + MinGW). Mã được viết bằng EclipseFP (Nó sử dụng Scion như IDE back-end) và được tích hợp vào một tệp thi hành với các cờ -O2.

Tôi cũng đã cố gắng xây dựng các gói bên ngoài IDE:

executable test 
    hs-source-dirs: src 
    main-is:   Main.hs 
    build-depends: base >= 4 
    ghc-options:  -O2 
    other-modules: Primes 

executable test2 
    hs-source-dirs: src2 
    main-is:   Main.hs 
    build-depends: base >= 4 
    ghc-options:  -O2 

Dưới đây là kết quả:

$ time test/test 
37550402023 

real 0m1.296s 
user 0m0.000s 
sys  0m0.031s 

$ time test2/test2 
37550402023 

real 0m0.520s 
user 0m0.015s 
sys  0m0.015s 

Trả lời

7

Tôi có thể tạo lại điều này nếu tôi đặt isPrimeprimes trong các mô-đun khác nhau. (Nếu chúng thuộc cùng một mô-đun, nhưng vẫn tách biệt với main, tôi không thấy khác biệt).

Thêm {-# INLINE isPrime #-} trả lại hiệu suất giống như có tất cả ba trong một mô-đun, do đó, có vẻ như GHC cần một cú hích để thực hiện nội tuyến mô-đun trong trường hợp này.

Đây là trên GHC 7.0.2, Ubuntu 11.04, 64-bit

+0

nó hoạt động! Cảm ơn! – claude

+5

GHC sẽ thực hiện nội tuyến rất tích cực trong một mô-đun, đặc biệt nếu hàm được gạch chân không được xuất. Nó ít háo hức hơn với các hàm nội tuyến trên các ranh giới mô-đun, trừ khi bạn INLINE chúng theo cách thủ công. –

1

Bạn đang chạy này bên GHCi hoặc biên soạn qua GHC? Tôi vừa thử một thử nghiệm, giữ tất cả các định nghĩa trong cùng một tệp, di chuyển hai tệp đầu tiên ra ngoài và biên dịch qua GHC bằng cờ -O và tắt. Không có sự khác biệt có thể nhận thấy giữa các kết hợp khác nhau trên máy của tôi (tất cả chỉ chạy một vài phần nghìn giây trên 1 giây, sử dụng GHC 7).

+0

Bạn có sử dụng '-O' hoặc' -O2'? IMHO nhiều tối ưu hóa có thể bị ảnh hưởng bởi chuyển động mã được kích hoạt bởi cờ thứ hai. – fuz

+0

Xây dựng thông tin môi trường được thêm vào bài đăng gốc, cảm ơn! – claude

+0

@FUZxxl Tôi thực sự đã thử cả hai. Không có sự khác biệt có thể nhận thấy trong cả hai trường hợp. Việc thực hiện nhanh nhất tổng thể là không có cờ tối ưu hóa được chuyển cho GHC, nhưng chúng ta đang nói về sự lan truyền tổng thể khoảng 100ms trong thời gian thực hiện giữa tất cả các cobminations trên máy của tôi. –

Các vấn đề liên quan