2017-12-20 21 views
2

벡터에 대해 수행하는 함수가 목록에 대해 parMap rpar 인 경우를 원합니다. 다음은 내가 가지고있는 것입니다.Haskell의 벡터에 대한 병렬 매핑

import Data.Vector 
import Control.Parallel.Strategies 

parMapVec :: (a -> b) -> Vector a -> Vector b 
parMapVec f = map (runEval . rpar . f) 

나는 이것이 어떻게 또는 왜 효과가 있을지 또는 왜 효과가 없는지에 대해 완전히 추론 할 수 없습니다.

또 다른 해결책은 Vector에게 Traversable의 인스턴스를 만든 다음 parTraversable을 사용할 수도 있지만 그건 그냥 parMap rpar 같은 것을 얻기 위해 많은 작업처럼 보인다.

+4

정확히 여기서 작동하지 않는 항목은 무엇입니까? 오류가 있습니까? 그렇다면 여기에 적어주십시오. – AJFarmar

+3

[vector strategies] (https://hackage.haskell.org/package/vector-strategies-0.4/docs/Data-Vector-Strategies.html) 패키지 사용을 고려하십시오. –

+1

@ ThomasM.DuBuisson 왜 패키지가 필요합니까? 패키지에는 정확히 하나의 함수가 있는데, 그 본문은 한 줄로되어 있습니다. – Alec

답변

0

Vector은 실제로 lierdakil이 지적한 Taversable의 인스턴스입니다. 내가이 아는 Data.Traversable page.

에서 인스턴스로 나열되지 않기 때문에이 아니라고 생각 나는 몇 가지 테스트 실행 : 나는 ghc --make ParVectorTest.hs -threaded -rtsopts 이것을 컴파일

import Control.Parallel.Strategies 
import Data.Vector as V 
import Data.Maybe 

parMapVec :: (a -> b) -> Vector a -> Vector b 
parMapVec f v = runEval $ evalTraversable rpar $ V.map f v 

range :: Integer -> Integer -> Vector Integer 
range x y 
    | x == y = x `cons` empty 
    | x < y = x `cons` (range (x + 1) y) 
    | x > y = (range x (y + 1)) `snoc` y 

fac :: Integer -> Integer 
fac n 
    | n < 2  = 1 
    | otherwise = n * (fac $ n - 1) 

main :: IO() 
main = do 
    let result = runEval $ do 
     let calc = parMapVec fac $ 80000 `range` 80007 
     rseq calc 
     return calc 
    putStrLn $ show result 

을하고 ./ParVectorTest -s 그것을 실행 발견 내가 대신 모두가 동시에 계승을 계산하는 계산 사이의 트레이드 오프의 프로세스 내 시스템 모니터에서 실행 지켜 코어가 더라 것을 제외하고, 좋은

SPARKS: 8 (7 converted, 0 overflowed, 0 dud, 0 GC'd, 1 fizzled) 

INIT time 0.001s ( 0.001s elapsed) 
MUT  time 5.460s ( 5.447s elapsed) 
GC  time 15.916s (15.893s elapsed) 
EXIT time 0.000s ( 0.000s elapsed) 
Total time 21.380s (21.342s elapsed) 

그. 이 직결되어

, 그래서 나는 main는 다음과 같은 방법으로 수정 된 테스트했다 :

main = do 
    let result = runEval $ do 
     let calc = parMap rpar fac [80000..80007] 
     rseq calc 
     return calc 
    putStrLn $ show result 

내가 컴파일을하고 찾을 수있는 동일한 방식으로 실행 :

SPARKS: 16 (14 converted, 0 overflowed, 0 dud, 1 GC'd, 1 fizzled) 

INIT time 0.001s ( 0.001s elapsed) 
MUT  time 5.412s ( 5.418s elapsed) 
GC  time 18.583s (18.537s elapsed) 
EXIT time 0.001s ( 0.000s elapsed) 
Total time 23.999s (23.957s elapsed) 

나 '를 왜 거기에 8 개가 아닌 16 개의 불꽃이 있었는지 모르겠지만 요점 외에는 있다고 생각합니다. 이 버전은 실제로 병렬로 수행되는 대신 프로세서간에 전달되는 것과 동일한 계산 동작을 보여줍니다.

따라서 목록을 사용하는 프로그램이나 벡터를 사용하는 프로그램이 모두 병렬로 실행되지는 않았지만 약간 더 빠른 벡터에 대해서는 parMap rpar 버전이 있습니다.

편집 : 나는 이유를 설명 할 수 없지만 parMapVec의 원래 버전을 사용하여 동일한 테스트를 실행하고 모든 스파크가 휘몰아 치는 것을 추가해야합니다.