coursera 강의 - Big Data Analysis with Scala and Spark를 보고 정리한 글입니다.
spark에서는 분산 처리 환경을 위해 두 종류의 연산을 제공합니다.
바로 lazy한 transformation과 eager한 action입니다.
(transformation과 action에 대해서 알고 싶다면 이 글을 참고하시면 될 것 같습니다)
이번 글에서는 action 연산 중 reduce 연산이 어떻게 분산되어 처리되는지 살펴보도록 하겠습니다.
컬렉션을 순차적으로 훑으며 인접해있는 요소들끼리 결합하여 하나의 결합된 결과를 내놓는 연산을 reduction operation이라고 합니다.
(walk through a collection and combine neigboring elements of the collection together to produce a single combined result)
scala의 reduction operation 함수로는 fold
, reduce
, aggregate
등이 있습니다.
scala의 foldLeft
같은 함수는 병렬성이 불가능합니다.
그 이유는 foldLeft
함수의 signature과 간단한 예제를 보면 알 수 있습니다.
foldLeft
함수의 signature은 아래와 같습니다.
def foldLeft[B](z: B)(f: (B, A) => B): B
또한 Scala API 문서에는 해당 컬렉션의 모든 요소를 맨 왼쪽부터 오른쪽으로 나아가며 연산을 적용하는 함수라고 foldLeft
를 소개합니다.
foldLeft
에 대해 이 정도만 이해하고 간단한 예제를 보도록 하겠습니다.
val xs = List(1, 2, 3, 4)
val res = xs.foldLeft("")((str: String, i: Int) => str + i)
이 예제의 결과로는 아마 String "1234"가 나올 것입니다.
여기서 foldLeft
의 signature을 기억한다면 유추할 수 있는 것이, List의 요소 타입인 Int를 중간 중간 결과를 내놓을 땐 String으로 강제 변경한다는 것입니다.
그렇다면 기존 List인 xs
를 만약 둘로 나누어 병렬적으로 foldLeft
를 진행한다면 어떻게 될까요?
첫번째 그룹인 List(1, 2)는 foldLeft
의 결과로 "12"가 나올 것이고, 두번째 그룹인 List(3, 4)는 foldLeft
의 결과로 "34"가 나올 것입니다.
여기서 각 그룹별 결과인 "12"와 "34"를 foldLeft
로 합칠 수 있을까요?
Int 타입을 받아 String 타입의 결과를 출력하려 하는데 입력 데이터인 "12"와 "34"는 Int가 아니기 때문에 입력 데이터로 사용될 수 없습니다.
결국 foldLeft
가 결과 타입을 A에서 B로 변경할 수 있다는 점은 병렬 처리된 결과 B를 다시 입력 타입인 A로 넣을 수 없게 되므로, 무조건 컬렉션의 요소를 왼쪽부터 오른쪽으로 순차적으로 연산해야 된다는 것을 의미합니다.
따라서 foldLeft
는 병렬화가 불가능한 함수입니다.
foldLeft
와 달리, fold
함수는 병렬성이 가능합니다.
이 함수의 signature은 아래와 같습니다.
def fold(z: A)(f: (A, A) => A): A
이 함수는 foldLeft
처럼 결과 타입을 A에서 B로 변경할 수 없고, 입력 데이터와 출력 데이터의 타입이 동일합니다.
따라서 컬렉션을 분할하여 병렬 처리하고 나중에 각 그룹별 결과들을 하나로 취합하는 것이 가능합니다.
fold
이외에도, reduce
, aggregate
함수도 병렬성이 가능합니다.
Scala에서는 크게 fold
, foldLeft/foldRight
, reduce
, aggregate
등의 컬렉션 reduction operation 등을 제공합니다.
그러나 Spark에서는 매우 큰 data set(RDD)의 분산 처리에 목적을 두고 있습니다.
Scala 컬렉션의 foldLeft/foldRight
같은 sequential한 함수는 매우 큰 data set을 처리하기에는 너무 시간적 비용이 많이 드는 함수입니다.
그렇기에 Spark의 data set인 RDD에서는 foldLeft/foldRight
함수를 제공하지 않습니다.
대신, fold
, reduce
, aggregate
등을 사용합니다.