2016-10-18 5 views
0

seqstrings에 고유 한 문자 수 (유니 코드 포함)를 계산하는 작은 운동 응용 프로그램을 작성 중이며 시도 할 때 aggregate을 사용하고 있습니다. 그목록에서 병렬 집계가 작동하지 않습니다. 길이가 8보다 작습니다.

object Frequency extends App { 

    val text = List("abc", "abc", "abc", "abc", "abc", "abc", "abc", "abc", "abc"); 

    def frequency(seq: Seq[String]):Map[Char, Int] = { 
    new Frequency(seq).calculate() 
    } 

    Console println frequency(seq=text) 
} 

의 사용을 생각하게

class Frequency(seq: Seq[String]) { 
    type FreqMap = Map[Char, Int] 

    def calculate() = { 
    val freqMap: FreqMap = Map[Char, Int]() 
    val pattern = "(\\p{L}+)".r 
    val seqop: (FreqMap, String) => FreqMap = (fm, s) => { 
     s.toLowerCase().foldLeft(freqMap){(fm, c) => 
     c match { 
      case pattern(char) => fm.get(char) match { 
      case None => fm+((char, 1)) 
      case Some(i) => fm.updated(char, i+1) 
      } 
      case _ => fm 
     } 
     } 
    } 

    val reduce: (FreqMap, FreqMap) => FreqMap = 
     (m1, m2) => { 
     m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0)) } 
     } 

    seq.par.aggregate(freqMap)(seqop, reduce) 

    } 
} 

다음 코드 : 여기

병렬

에서 실행하려면 내 코드입니다 나는 "abc" 년대의 번호를 그대로 결과가 Map(a -> 8, b -> 8, c -> 8)이다 "ABC"9 번을 공급> 8

내가 this을 검토 한 결과, 나는 제대로

집계를 사용하고 것처럼 보인다 작동하게하려면 어떤 제안이 필요합니까?

답변

2

seqop에 이미 수집 된 결과 (첫 번째 fm)가 삭제됩니다. 계산중인 새 결과에이를 추가해야합니다. 예 : 다음과 같이하십시오 :

def calculate() = { 
    val freqMap: FreqMap = Map[Char, Int]() 
    val pattern = "(\\p{L}+)".r 
    val reduce: (FreqMap, FreqMap) => FreqMap = 
     (m1, m2) => { 
     m1 ++ m2.map { case (k, v) => k -> (v + m1.getOrElse(k, 0)) } 
     } 
    val seqop: (FreqMap, String) => FreqMap = (fm, s) => { 
     val res = s.toLowerCase().foldLeft(freqMap){(fm, c) => 
     c match { 
      case pattern(char) => fm.get(char) match { 
      case None => fm+((char, 1)) 
      case Some(i) => fm.updated(char, i+1) 
      } 
      case _ => fm 
     } 
     } 

     // I'm reusing your existing combinator function here: 
     reduce(res,fm) 
    } 

    seq.par.aggregate(freqMap)(seqop, reduce) 
} 

병렬 수집이 작업을 어떻게 나누 느냐에 따라 일부를 버립니다. 귀하의 경우 (9x "abc") 8 개의 병렬 seqop 연산으로 항목을 나눕니다. 즉, 정확히 하나의 결과 집합을 버립니다. 이것은 숫자에 따라 다르며, 17x "abc"로 실행하면 13 개의 병렬 연산으로 실행되며 4 개의 결과 세트가 삭제됩니다 (어쨌든 내 컴퓨터에서 - 기본 코드에 익숙하지 않고 작업을 구분하는 방법은 다음과 같습니다. 아마도 사용 된 ExecutionContext/Threadpool과 그 이후의 CPU/코어 수에 따라 달라집니다).

일반적으로 병렬 컬렉션은 순차적 컬렉션을 대체하는 드롭입니다. 즉, .par을 드롭하면 대개 느려지더라도 동일한 결과가 나타납니다. 원래 코드로이 작업을 수행하면 결과가 1로 표시되어 병렬화 문제가 아니라는 것을 알 수 있습니다. 이것은 이들을 사용할 때 올바른 일을하는지 테스트하는 좋은 방법입니다.

마지막으로 중요한 점은 동일한 변수 이름을 두 번 사용하고이어서 fm을 음영 처리하기 때문에 평상시보다 더 어려워졌습니다. 그렇게하지 않으면 코드를 더 읽기 쉽고 실수를 쉽게 찾아 낼 수 있습니다.

+0

감사합니다. –