Sau khi đọc Stack Overflow câu hỏi Using vectors for performance improvement in Haskell mô tả một nhanh tại chỗ quicksort trong Haskell, tôi đặt ra cho mình hai mục tiêu:phân loại nhanh trong Haskell
Thực hiện các thuật toán tương tự với một trung bình của ba để tránh xấu biểu diễn trên các véc tơ được sắp xếp trước;
Tạo phiên bản song song.
Đây là kết quả (một số mảnh nhỏ đã bị bỏ lại vì đơn giản):
import qualified Data.Vector.Unboxed.Mutable as MV
import qualified Data.Vector.Generic.Mutable as GM
type Vector = MV.IOVector Int
type Sort = Vector -> IO()
medianofthreepartition :: Vector -> Int -> IO Int
medianofthreepartition uv li = do
p1 <- MV.unsafeRead uv li
p2 <- MV.unsafeRead uv $ li `div` 2
p3 <- MV.unsafeRead uv 0
let p = median p1 p2 p3
GM.unstablePartition (< p) uv
vquicksort :: Sort
vquicksort uv = do
let li = MV.length uv - 1
j <- medianofthreepartition uv li
when (j > 1) (vquicksort (MV.unsafeSlice 0 j uv))
when (j + 1 < li) (vquicksort (MV.unsafeSlice (j+1) (li-j) uv))
vparquicksort :: Sort
vparquicksort uv = do
let li = MV.length uv - 1
j <- medianofthreepartition uv li
t1 <- tryfork (j > 1) (vparquicksort (MV.unsafeSlice 0 j uv))
t2 <- tryfork (j + 1 < li) (vparquicksort (MV.unsafeSlice (j+1) (li-j) uv))
wait t1
wait t2
tryfork :: Bool -> IO() -> IO (Maybe (MVar()))
tryfork False _ = return Nothing
tryfork True action = do
done <- newEmptyMVar :: IO (MVar())
_ <- forkFinally action (\_ -> putMVar done())
return $ Just done
wait :: Maybe (MVar()) -> IO()
wait Nothing = return()
wait (Just done) = swapMVar done()
median :: Int -> Int -> Int -> Int
median a b c
| a > b =
if b > c then b
else if a > c then c
else a
| otherwise =
if a > c then a
else if b > c then c
else b
Đối với vectơ với 1.000.000 yếu tố, tôi nhận được kết quả sau:
"Number of threads: 4"
"**** Parallel ****"
"Testing sort with length: 1000000"
"Creating vector"
"Printing vector"
"Sorting random vector"
CPU time: 12.30 s
"Sorting ordered vector"
CPU time: 9.44 s
"**** Single thread ****"
"Testing sort with length: 1000000"
"Creating vector"
"Printing vector"
"Sorting random vector"
CPU time: 0.27 s
"Sorting ordered vector"
CPU time: 0.39 s
Câu hỏi của tôi là:
- Tại sao biểu diễn sti sẽ giảm với một vector được sắp xếp trước?
- Tại sao sử dụng forkIO và bốn luồng không cải thiện hiệu suất?
Tôi sắp đi ngủ, vì vậy không phân tích ngay bây giờ, chỉ là những gì nhảy ra ngoài. Khi bạn đang tìm kiếm trên mọi cuộc gọi đệ quy, bạn đang tạo ra rất nhiều chủ đề, chủ đề lập kế hoạch trên luồng sẽ áp đảo công việc thực tế cần thực hiện. Nếu thậm chí có đồng bộ hóa giữa các luồng khác nhau truy cập vào mảng liên quan, điều đó sẽ giết hiệu suất hoàn toàn ngay cả đối với ít chuỗi hơn. Nếu bạn muốn một tăng tốc, ngã ba chỉ cho vài cuộc gọi đệ quy đầu tiên không có nhiều chủ đề chạy hơn bạn có lõi. –
Đối với chủ nghĩa song song nhanh, bạn muốn sử dụng 'par', không phải' forkIO'. Xem gói 'song song' [ở đây] (http://hackage.haskell.org/package/parallel-3.2.0.3) để biết thêm chi tiết. –
@GabrielGonzalez hiện 'par' hoạt động tốt với tính toán là" chỉ "IO hoạt động? Ngoài ra, có cần phải hiểu mô-đun Control.Parallel.Strategies không? – Simon