Spark의 reduction operation (Spark에서 foldLeft가 없는 이유)

Keunjae Song·2020년 3월 31일
0

coursera 강의 - Big Data Analysis with Scala and Spark를 보고 정리한 글입니다.

서론

spark에서는 분산 처리 환경을 위해 두 종류의 연산을 제공합니다.
바로 lazy한 transformation과 eager한 action입니다.
(transformation과 action에 대해서 알고 싶다면 이 글을 참고하시면 될 것 같습니다)

이번 글에서는 action 연산 중 reduce 연산이 어떻게 분산되어 처리되는지 살펴보도록 하겠습니다.

Reduction operation이란?

컬렉션을 순차적으로 훑으며 인접해있는 요소들끼리 결합하여 하나의 결합된 결과를 내놓는 연산을 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 등이 있습니다.

Reduction opertaion의 병렬성 가능 여부

병렬성이 불가능한 reduction opertaion

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는 병렬화가 불가능한 함수입니다.

병렬성이 가능한 reduction operation

foldLeft와 달리, fold 함수는 병렬성이 가능합니다.
이 함수의 signature은 아래와 같습니다.
def fold(z: A)(f: (A, A) => A): A
이 함수는 foldLeft처럼 결과 타입을 A에서 B로 변경할 수 없고, 입력 데이터와 출력 데이터의 타입이 동일합니다.
따라서 컬렉션을 분할하여 병렬 처리하고 나중에 각 그룹별 결과들을 하나로 취합하는 것이 가능합니다.

fold 이외에도, reduce, aggregate 함수도 병렬성이 가능합니다.

Scala와 Spark의 사용 가능한 reduction opertion

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 등을 사용합니다.

0개의 댓글