복붙노트

[SCALA] 차이가 감소하고 foldLeft / 함수형 프로그래밍 (특히 스칼라 및 스칼라 API)를 폴드 간의?

SCALA

차이가 감소하고 foldLeft / 함수형 프로그래밍 (특히 스칼라 및 스칼라 API)를 폴드 간의?

왜 모두 스칼라와 스파크 화상을 입을 같은 프레임 워크를 줄이고 foldLeft해야합니까? 그럼 줄이고 배의 차이는 무엇인가?

해결법

  1. ==============================

    1.하지 분명이 주제와 관련된 다른 유래 대답에 언급 된 큰 큰 차이는, 그는 교환 법칙이 성립 모노 이드, 교환 법칙과 결합 모두 즉 작업을 부여해야 줄일 수있다. 이 동작은 병렬 처리 될 수 있다는 것을 의미한다.

    하지 분명이 주제와 관련된 다른 유래 대답에 언급 된 큰 큰 차이는, 그는 교환 법칙이 성립 모노 이드, 교환 법칙과 결합 모두 즉 작업을 부여해야 줄일 수있다. 이 동작은 병렬 처리 될 수 있다는 것을 의미한다.

    이러한 구분은 빅 데이터 / MPP / 분산 컴퓨팅을 위해 매우 중요하며, 감소 이유는 전체 이유도 존재한다. 컬렉션은 처단 할 수 있으며, 다음 각 청크의 결과에 작동 할 수 감소, 각 청크에서 작동 할 수 감소 - 사실 깊은 한 수준을 정지 할 필요가 청크의 수준을. 우리는 너무 각 청크를 잘라 수 있습니다. CPU가 무한대가 주어진다면리스트에 정수를 가산하는 단계는 O (N 로그) 이유이다.

    방금 서명 보면 당신은 당신이 가진 foldLeft으로 줄일 수있는 모든 것을 달성 할 수 있기 때문에 존재 감소에 대한 이유가 없다. foldLeft의 기능 감소의 기능보다 더 크다.

    그것의 실행은 항상 O (N) (당신은 교환 법칙이 성립 모노 이드에 공급하는 경우에도) 그래서하지만 당신은 foldLeft을 병렬화 할 수 없습니다. 이 동작은 가환 모노 이드 아니며 따라서 누적 값이 순차적으로 집계 일련의 계산한다 가정한다 때문이다.

    foldLeft은 교환 법칙도 연관성을지지 않습니다. 이 컬렉션을 절단 할 수있는 기능을 제공 연관성, 그리고 그것은 (는 덩어리의 각각에서 각 결과를 집계하는 순서는 중요하지 않도록) 순서가 중요하지 않기 때문에 쉽게 축적되는하게 교환 법칙입니다. 엄밀히 말하면 교환 법칙이 정렬 알고리즘 분산 예를 들어, 그냥 당신이 당신의 덩어리 순서화를 제공 할 필요가 없기 때문에 논리 쉽게 병렬화 필요하지 않습니다.

    당신이 그것을 줄이기위한 스파크 문서를 읽어보십시오 구체적으로 말한다 "... 교환 법칙과 연관 이항 연산자"

    http://spark.apache.org/docs/1.0.0/api/scala/index.html#org.apache.spark.rdd.RDD

    여기 감소 증거 foldLeft 단지 특별한 경우가 없습니다

    scala> val intParList: ParSeq[Int] = (1 to 100000).map(_ => scala.util.Random.nextInt()).par
    
    scala> timeMany(1000, intParList.reduce(_ + _))
    Took 462.395867 milli seconds
    
    scala> timeMany(1000, intParList.foldLeft(0)(_ + _))
    Took 2589.363031 milli seconds
    

    그것은 조금 FP / 수학 뿌리 가까이하고, 설명하기 조금 까다 얻는 경우 지금 이것은이다. orderless 모음 (멀티 세트)를 다루는 MapReduce의 패러다임의 일부로 형식적 정의 감소 폴드 재귀 공식적으로 정의 (catamorphism 참조) 따라서 수집하는 구조 / 시퀀스를 가정한다.

    덩어리가 순서를 가지고 만 접어하지 않기 때문에 (엄격한)지도에서 우리가 배를 정의 할 수 없습니다 프로그래밍 모델을 줄일 수 있기 때문에 끓는에는 배 방법은 연관성이 아니라 교환 법칙이 필요 없습니다.

    간단히 말해서, 누적의 순서없이 작품을 감소, 배는 누적의 순서를 필요로하며 NOT을 구별 제로 값의 존재를 0 값을 필요로 누적의 순서입니다. 엄밀하게는 제로 값 (X) 연산 및 y =의 X를 해결 한 후, 임의의 값 (x)을 복용하여 추론하여 있기 때문에, 빈 수집 작동해야 감소 말하기하지만 좌측이 존재할 수 있으므로 그 비 상호적인 동작으로 작동하지 않는다 그리고 별개 오른쪽 제로 값 (즉, X, Y 연산! = Y 연산 X). 물론 스칼라 그래서 그냥 예외를 throw, 즉 (아마 uncomputable입니다) 어떤 수학을하고 필요로이 영점이 무엇인지 일을 귀찮게하지 않습니다.

    프로그램의 유일한 명백한 차이가 서명 때문에이 원래의 수학적 의미가 손실 된 것을 (종종 어원에서의 경우와 같이)이 보인다. 결과보다는이 맵리 듀스에서 원래 의미의 보존, 배의 동의어가되었다 줄일 것입니다. 이제 이들 용어는 종종 같은 의미로 사용하고 (빈 컬렉션을 무시하고) 대부분의 구현에서 동일하게 동작한다. 불가사의는 우리가 지금 해결해야한다는, 스파크에서 같은 특수성에 의해 악화된다.

    그래서 스파크는 배를 가지고 있지만, (글을 쓰는 시점에서) 서브 결과 (각 파티션에 대해 하나)가 결합되는 순서는 작업이 완료되는 순서입니다 - 따라서 비 결정적. 그 배를 지적 @CafeFeed하는 덕분에 코드를 읽은 후 나는 그것이 비 결정적이다 것을 깨달았다 runJob를 사용합니다. 또한 혼란은 treeReduce하지만 treeFold을 가진 스파크에 의해 생성된다.

    줄이고 비어 있지 않은 시퀀스에 적용되는 경우에도 배 차이가 있습니다. 전자는 임의의 순서로 컬렉션에서의 MapReduce 프로그래밍 패러다임 (http://theory.stanford.edu/~sergei/papers/soda10-mrc.pdf)의 일부로 정의되고, 하나의 연산자가있을뿐 아니라 가환 있다고 가정한다고 연관은 결정 결과를 제공합니다. 후자는 catomorphisms의 관점에서 정의되고, 따라서 가환 연산자를 필요로하지 않는, 컬렉션 순서의 개념이 (또는 연결리스트와 같은 재귀 적 정의)해야한다.

    실제로 때문에 프로그래밍의 unmathematical 특성으로 하나 제대로 (스칼라처럼) 또는 잘못 (불꽃처럼) 감소와 같은 방식으로 행동하는 경향이 접습니다.

    내 의견은 용어 배의 사용이 완전히 스파크에 떨어 된 경우 혼란을 피할 것입니다. 적어도 스파크는 문서에 메모를 가지고있다 :

  2. ==============================

    2.내가 착각하고 있지 않다 경우, 스파크 API가 필요하지 않는 경우에도, 또한 접 f는 교환 법칙이 성립 될 수 있도록해야합니다. 파티션이 보장되지 않는 집계되는 순서 때문에. 다음 코드에서 예를 들어 첫 번째 프린트 아웃 정렬 :

    내가 착각하고 있지 않다 경우, 스파크 API가 필요하지 않는 경우에도, 또한 접 f는 교환 법칙이 성립 될 수 있도록해야합니다. 파티션이 보장되지 않는 집계되는 순서 때문에. 다음 코드에서 예를 들어 첫 번째 프린트 아웃 정렬 :

    import org.apache.spark.{SparkConf, SparkContext}
    
    object FoldExample extends App{
    
      val conf = new SparkConf()
        .setMaster("local[*]")
        .setAppName("Simple Application")
      implicit val sc = new SparkContext(conf)
    
      val range = ('a' to 'z').map(_.toString)
      val rdd = sc.parallelize(range)
    
      println(range.reduce(_ + _))
      println(rdd.reduce(_ + _))
      println(rdd.fold("")(_ + _))
    }  
    

    인쇄 :

    ABCDEFGHIJKLMNOPQRSTUVWXYZ

    abcghituvjklmwxyzqrsdefnop

    defghinopjklmqrstuvabcwxyz

  3. ==============================

    3.끓는에 대한 또 다른 차이는 하둡에서 결합기를 사용하는 것입니다.

    끓는에 대한 또 다른 차이는 하둡에서 결합기를 사용하는 것입니다.

    이 감속기에 대한 모든 데이터를 정렬 / 셔플의 대신지도 측면에 적용됩니다 감소와 함께, 귀하의 작업이 교환 법칙이 성립 모노 이드입니다 상상해보십시오. foldLeft으로이 사건을하지 않습니다.

    pipe.groupBy('product) {
       _.reduce('price -> 'total){ (sum: Double, price: Double) => sum + price }
       // reduce is .mapReduceMap in disguise
    }
    
    pipe.groupBy('product) {
       _.foldLeft('price -> 'total)(0.0){ (sum: Double, price: Double) => sum + price }
    }
    

    항상 끓는에서 모노 이드로 작업을 정의하는 것이 좋습니다.

  4. ==============================

    4.아파치 스파크에 접어하는 것은 분산 컬렉션에 배와 동일하지 않습니다. 사실 그것은 결정적 결과를 생성하는 가환 기능이 필요합니다

    아파치 스파크에 접어하는 것은 분산 컬렉션에 배와 동일하지 않습니다. 사실 그것은 결정적 결과를 생성하는 가환 기능이 필요합니다

    이 미사 엘 로젠탈으로 표시하고 자신의 의견에 Make42에 의해 제안되었다.

    관찰 된 행동이 사실 PARALLELIZE 셔플하지 않는 경우 HashPartitioner 관련되어 HashPartitioner를 사용하지 않는 것이 좋습니다 됐어요.

    import org.apache.spark.sql.SparkSession
    
    /* Note: standalone (non-local) mode */
    val master = "spark://...:7077"  
    
    val spark = SparkSession.builder.master(master).getOrCreate()
    
    /* Note: deterministic order */
    val rdd = sc.parallelize(Seq("a", "b", "c", "d"), 4).sortBy(identity[String])
    require(rdd.collect.sliding(2).forall { case Array(x, y) => x < y })
    
    /* Note: all posible permutations */
    require(Seq.fill(1000)(rdd.fold("")(_ + _)).toSet.size == 24)
    

    설명 :

    EET 용 배의 구조

    def fold(zeroValue: T)(op: (T, T) => T): T = withScope {
      var jobResult: T
      val cleanOp: (T, T) => T
      val foldPartition = Iterator[T] => T
      val mergeResult: (Int, T) => Unit
      sc.runJob(this, foldPartition, mergeResult)
      jobResult
    }
    

    RDD 줄이기위한 구조와 동일하다 :

    def reduce(f: (T, T) => T): T = withScope {
      val cleanF: (T, T) => T
      val reducePartition: Iterator[T] => Option[T]
      var jobResult: Option[T]
      val mergeResult =  (Int, Option[T]) => Unit
      sc.runJob(this, reducePartition, mergeResult)
      jobResult.getOrElse(throw new UnsupportedOperationException("empty collection"))
    }
    

    여기서 runJob는 교환 적 기능을 필요로하는 파티션에 순서 무시하고 결과로 수행된다.

    foldPartition 및 reducePartition는 TraversableOnce reduceLeft에 의해 구현 및 foldLeft 처리 순서 효과적으로 (상속 위임함으로써)면에서 동등하다.

    결론 : RDD에 접어 청크의 순서에 따라 달라집니다 및 교환 법칙과 연관성이 필요 없습니다.

  5. from https://stackoverflow.com/questions/25158780/difference-between-reduce-and-foldleft-fold-in-functional-programming-particula by cc-by-sa and MIT license