빅 데이터가 작동해야하는 이유


9

최근 인턴쉽을 위해 Big Data와 관련된 새로운 프로젝트를 시작했습니다. 관리자들은 기능적 프로그래밍 학습을 시작하도록 권장했습니다 (Scala를 적극 권장합니다). F #을 사용한 경험이 적었지만, 프로그래밍의 패러다임을 사용하는 것이 중요하다는 것을 알 수 없었습니다.

딘은이 주제에 대한 흥미로운 이야기를주고, 여기에 왜 "빅 데이터"에 대한 자신의 생각을 공유 : http://www.youtube.com/watch?v=DFAdLCqDbLQ을 하지만 빅 데이터가 의미하는 것은 아니다으로 매우 편리하지 않았다 하둡 만

BigData는 매우 모호한 개념입니다. 한동안 잊어 버렸습니다. 우리가 데이터를 다룰 때 여러 가지 측면을 비교하고 기능적인 방법이 비싸지 않은지 알아보기 위해 간단한 예를 생각해 냈습니다. 함수형 프로그래밍이 작은 데이터에 비싸고 메모리 소비가 많은 경우 왜 빅 데이터에 필요한가?

멋진 도구와는 달리, 세 가지 접근 방식, 즉 명령 방식과 기능 방식 (재귀, 컬렉션 사용)을 사용하여 하나의 구체적이고 인기있는 문제에 대한 솔루션을 만들려고했습니다. 세 가지 방법을 비교하기 위해 시간과 복잡성을 비교했습니다.

스칼라를 사용하여 이러한 기능을 작성하는 것은 세 가지 패러다임을 사용하여 알고리즘을 작성하는 가장 좋은 도구이므로

def main(args: Array[String]) {
    val start = System.currentTimeMillis()
    // Fibonacci_P
    val s = Fibonacci_P(400000000)
    val end = System.currentTimeMillis()
    println("Functional way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s, end - start))
    val start2 = System.currentTimeMillis()

    // Fibonacci_I
    val s2 = Fibonacci_I(40000000 0)
    val end2 = System.currentTimeMillis();
    println("Imperative way: \n the Fibonacci sequence whose values do not exceed four million : %d \n Time : %d ".format(s2, end2 - start2))
}

기능적인 방법 :

def Fibonacci_P(max: BigInt): BigInt = {
    //http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.Stream
    //lazy val Fibonaccis: Stream[Long] = 0 #:: 1 #:: Fibonaccis.zip(Fibonaccis.tail).map { case (a, b) => a + b }
    lazy val fibs: Stream[BigInt] = BigInt(0)#::BigInt(1)#::fibs.zip(fibs.tail).map {
        n = > n._1 + n._2
    }
    // println(fibs.takeWhile(p => p < max).toList)
    fibs.takeWhile(p = > p < max).foldLeft(BigInt(0))(_ + _)
}

재귀 적 방법 :

def Fibonacci_R(n: Int): BigInt = n match {
    case 1 | 2 = > 1
    case _ = > Fibonacci_R(n - 1) + Fibonacci_R(n - 2)
}

명령 방식 :

def Fibonacci_I(max: BigInt): BigInt = {
    var first_element: BigInt = 0
    var second_element: BigInt = 1
    var sum: BigInt = 0

    while (second_element < max) {
        sum += second_element

        second_element = first_element + second_element
        first_element = second_element - first_element
    }

    //Return 
    sum
}

함수형 프로그래밍이 무겁다는 것을 알았습니다! 시간이 오래 걸리고 메모리에서 더 많은 공간을 소비합니다. 기사를 읽거나 대화를 볼 때마다 데이터 과학에서 함수형 프로그래밍을 사용해야한다고 혼동됩니다. 사실, 특히 데이터 세계에서보다 쉽고 생산적입니다. 그러나 더 많은 시간과 메모리 공간이 필요합니다.

그렇다면 빅 데이터에서 함수형 프로그래밍을 사용해야하는 이유는 무엇입니까? 빅 데이터에 함수형 프로그래밍 (Scala)을 사용하는 모범 사례는 무엇입니까?


5
함수형 프로그래밍을 사용하면 코드를 쉽게 병렬화 할 수 있으므로 단일 작업을 단일 스레드에서 실행하는 데 더 많은 시간이 걸리더라도 병렬 처리로 인해 전반적인 성능이 향상 될 수 있습니다.
Giorgio

@Giorgio : 병렬 처리에 최고의 성능을 얻기 위해 Actor Modeling과는 다른 패러다임이 있습니다. 그렇게 생각하지 않습니까?
user3047512

2
hadoop의 map / reduce 접근 방식이 함수형 프로그래밍의 아이디어이기 때문에 단순히 추측합니다.
Doc Brown

1
@ user3047512 : 예를 들어, Erlang은 액터 모델을 사용하며 대부분 기능적입니다.
Giorgio

2
"빅 데이터"페이드와 FP 간의 연결은 그렇게 간단하지 않습니다. "빅 데이터 (Big data)"에서, ​​소위 맵-리 듀스 접근법은 유행 적이며, 결과적으로 기능적 프로그래밍 정신에 의해 다소 영감을 얻었습니다. 이것은 유사성이 끝나는 곳입니다.이 두 세계 사이에 더 이상 연결이 보이지 않습니다.
SK-logic

답변:


13

내가 보는 방법은 다음과 같습니다.

  • "big data"라는 단어는 잠시 모호한 개념 이므로 무시하십시오.

  • 하둡에 대해 언급했습니다. 하둡은 두 가지 일을한다 : 하나의 단일 드라이브 인 것처럼 하둡의 API를 통해 액세스 할 수있는 중복성을 가진 여러 머신에 분산 된 일종의 "가상"드라이브를 가질 수있다. 하둡 분산 파일 시스템 에서와 같이 HDFS라고 합니다 . Hadoop이 수행하는 다른 작업은 Map-Reduce 작업을 실행할 수 있도록하는 것입니다 (Map-Reduce의 프레임 워크 임). 우리가 선택하면 맵리 듀스의 위키피디아 페이지를 , 우리는 그 참조 :

MapReduce는 클러스터에서 병렬 분산 알고리즘을 사용하여 대용량 데이터 세트를 처리하기위한 프로그래밍 모델입니다.

...

MapReduce 프로그램은 필터링 및 정렬을 수행하는 Map () 프로 시저 (예 : 이름을 기준으로 학생 정렬, 각 이름 당 하나의 큐) 및 요약 작업을 수행하는 Reduce () 프로 시저 (예 : 수 계산)로 구성됩니다. 각 대기열에있는 학생들의 이름 빈도를 산출)

...

'MapReduce'는 많은 수의 컴퓨터를 사용하여 거대한 데이터 세트에서 병렬화 가능한 문제를 처리하기위한 프레임 워크입니다.

또한이 페이지에서 하둡은 다음과 같이 설명됩니다.

Hadoop, Apache의 무료 및 오픈 소스 MapReduce 구현.

이제 Hadoop은 기능 언어가 아닌 Java로 작성되었습니다. 또한 Hadoop의 페이지를 보면 Java에서 MapReduce 작업을 작성하고 Hadoop 클러스터에 배치하는 방법에 대한 예제있습니다 .

Hadoop을위한 Fibonnaci MapReduce 작업의 Java 예제는 다음과 같습니다.

나는 이것이 귀하의 질문, 즉 BigData, 특히 피보나치 작성 MapReduce 작업이 기능적으로 필요하지 않기 때문에 귀하의 질문에 대답하기를 바랍니다.

물론 이는 BigData가 OO 전용이어야한다는 것을 의미하지는 않습니다. 기능적 언어를 사용하여 MapReduce와 같은 작업을 구현할 수 있습니다. 예를 들어 Scalding을 통해 원하는 경우 Hadoop과 함께 Scala를 사용할 수 있습니다 .

내가 말할 가치가 있다고 생각하는 다른 점들.

스칼라에서 재귀를 할 때 코드에서 허용하면 스칼라는 테일 콜 최적화를 수행 합니다. 때문에, JVM이 없습니다 (아직) 지원 꼬리 호출 최적화를 수행 , 스칼라, 루프 해당하는 코드와 재귀 호출, 컴파일시에, 교체하여이를 달성 으로 여기에서 설명 . 이것이 기본적으로 의미하는 것은 Scala를 사용하여 재귀 적 코드와 비재 귀적 코드 벤치 마크를 수행하는 것은 런타임에 동일한 일을 끝내기 때문에 의미가 없다는 것입니다.


2
OP에서 제안한 벤치 마크를 손상시키는 테일 콜 최적화를 지원하지 않는 JVM에 대해 훌륭한 지적을합니다. 이것은 매우 유익한 답변입니다. 감사합니다.
maple_shaft

1
답변 주셔서 감사합니다, 예! 테일 콜 최적화는 숨겨진 스칼라 기능 중 하나입니다. stackoverflow.com/questions/1025181/hidden-features-of-scala/… . "빅 데이터"의 문제 중 하나는 모든 회사가 다른 방식으로 새로운 기술을 구축하려고한다는 것입니다. 그러나 주로 Hadoop 기술과 다른 두 가지가 있습니다. 당신이 말했듯이, 그것은 주관적이고 자체 문제와 관련이 있기 때문에 우리는 전문 지식을 바탕으로 올바른 프로그래밍 패러다임을 선택해야합니다. 예를 들어, 실시간 예측 모델은 Hadoop 플랫폼에서 제대로 작동하지 않습니다.
user3047512

9

단일 머신에서 실행할 수있는 한 "빅 데이터"가 아닙니다. 귀하의 예제 문제는 그것에 대해 아무것도 설명하기에 완전히 부적절합니다.

빅 데이터는 문제의 크기가 너무 커서 처리를 배포하는 것이 최적화가 아니라 기본 요구 사항임을 의미합니다. 또한 함수형 프로그래밍을 사용하면 변경 불가능한 데이터 구조와 상태 비 저장으로 인해 정확하고 효율적인 분산 코드를 훨씬 쉽게 작성할 수 있습니다.


"빅 데이터는 문제의 크기가 너무 커서 처리를 배포하는 것이 최적화가 아니라 기본 요구 사항임을 의미합니다." -한 대의 기계를 사용하여 해결할 수없는 문제는 무엇인지 이해하지 못하며 N> 1 인 경우 N 이상이 필요합니다.
Shivan Dragon

6
@ShivanDragon : 단일 시스템에서 완전히 충족시킬 수없는 성능 요구 사항을 포함하는 문제. 또는 데이터 크기가 너무 커서 단일 시스템으로 모든 데이터를 저장할 수도 없습니다.
Michael Borgwardt

죄송합니다. 지금 요점을 봅니다. 더 구체적으로 말하면 BigData의 우산 아래에있는 MapReduce입니다.
Shivan Dragon

의견을 보내 주셔서 감사합니다. 동의합니다. 어쩌면 나는 내 관점을 보여주는 좋은 간단한 예를 찾지 못했습니다. "빅 데이터"는 여전히 개발자가 데이터를 사용하여 3V 정의를 고려하여 일상적인 문제를 해결하는 방법입니다. 나는 3V를 잠시 잊어 버리고 데이터를 다루는 매우 간단한 측면에 대해 이야기 할 것입니다. 기능적인 방식으로 데이터를 분석하는 것이 비용이 많이 든다면 왜 "빅 데이터"가 기능적이어야한다고 말하는가? 이것이 내 요점입니다.
user3047512

4
예를 들어, @ShivanDragon은 LHC가 초당 몇 기가 바이트의 데이터를 생성하고 있습니다 . 단일 시스템이 이러한 처리량을 처리 할 수 ​​있는지 확실하지 않습니다.
SK-logic

4

스칼라를 모르므로 기능적 접근 방식에 대해서는 언급 할 수 없지만 코드는 과도하게 보입니다.

반면에 재귀 함수는 비효율적입니다. 함수가 자신을 두 번 호출하기 때문에 2 ^ n 차수이므로 매우 비효율적입니다. 세 가지 접근 방식을 비교하려면 세 가지 최적 구현을 ​​비교해야합니다.

피보나치 함수는 함수를 한 번만 호출하여 재귀 적으로 구현할 수 있습니다. 보다 일반적인 정의를 보자.

F(0) = f0
F(1) = f1
F(n) = F(n-1) + F(n-2)

표준 특수 사례는 다음과 같습니다.

f0 = 0
f1 = 1

일반적인 재귀 함수는 다음과 같습니다.

function fibonacci($f0, $f1, $n){
    if($n < 0 || !isInt($n)) return false;
    if($n = 0) return $f0;
    if($n = 1) return $f1;
    return fibonacci($f1, $f0 + $f1, $n - 1);
}

감사! 당신은 좋은 지적을했지만 반복적 인 방법으로 할 수있는 효과적인 방법은 없습니다. 이것은 매우 일반적인 프로브입니다 (피보나치 스위트). 이것이 세 가지 방법으로 같은 문제를 해결하는 데 있습니다. 프로그래밍 언어를 사용 하여이 프로브를 해결하는 더 좋은 방법을 제안 할 수 있습니까? 스칼라를 사용하여 다시 작성하고 동일한 테스트를 수행 할 수 있습니까?
user3047512

@ user3047512 꼬리 재귀를 지원하는 언어의 경우 누산기로이를 작성할 수 있습니다.
toasted_flakes

스칼라는 또한 숨겨진 기능으로 꼬리 재귀를 지원합니다. oldfashionedsoftware.com/2008/09/27/…
user3047512

1
@ user3047512 재귀 솔루션은 순수한 함수이기 때문에 (출력은 함수 args에만 의존하고 그 밖의 것은 없다 ) 메모리 화 는 좋은 솔루션이다. 간단히 말해, 값을 반환하고, 인수를 저장하고 키 / 값 해시를 생성 할 때마다, 그리고 함수가 실행될 때마다 먼저 살펴보십시오. 기존의 해시 값을 찾아 할 것입니다이 기능에 대한 미래의 호출 - 이것은 순수한 기능의 장점 중 하나입니다 제로 우리는 결과가 변경되지 않습니다 알고 있기 때문에, 계산을.
이즈 카타

@ user3047512 반복적 인 버전도이 경우 순수한 함수처럼 보이지만, 항상 그런 것은 아닙니다. 기능적 언어에서는 언어에 의해 더 잘 적용된다고 생각합니다 ...
Izkata

0

함수형 프로그래밍이 작은 데이터에 비싸고 메모리 소비가 많은 경우 왜 빅 데이터에 필요한가?

특히 나는 이것이 매우 유용한 몇 가지 응용 프로그램을 이미 볼 수 있습니다. 전의. 통계, 즉 데이터 분석을 위해 다른 매개 변수 또는 매개 변수 세트로 즉석에서 가우시안 함수를 계산합니다. 수치 분석 등을위한 보간도 있습니다.

빅 데이터에 함수형 프로그래밍 (Scala)을 사용하는 모범 사례는 무엇입니까?

효율성에 대한 답을 얻기 위해 공간이나 시간의 효율성, 특히 재귀, 꼬리 재귀 , 연속 전달 스타일 , 고차 함수 등을 향상시키는 데 도움이되는 기술도 있습니다 . 일부 언어에는 장단점이 있습니다 (예 : 게으른 대 열망). 피보나치 수열과 같은 단순한 것 나는 때때로 동료가 일부는 꺼려하고 함수형 프로그래밍에 익숙하지 않아서 더 많은 개발 시간을 소비한다는 것을 알기 때문에 명령 방식을 사용할 수 있습니다 ... 빠르고 책임감 있고 "읽기 쉬운"(이 주관적인 코드를 찾았지만) 찾을 수 있기 때문에 함수형 프로그래밍을 사용해야합니다.

Wikipedia에는 ​​피보나치 수열의 "빠른"버전이 게시되어 있습니다. https://en.wikipedia.org/wiki/Functional_programming#Scala

def fibTailRec(n: Int): Int = {
  @tailrec def f(a: Int, b: Int, c: Int): Int = if (a == 0) 0 else if(a < 2) c else f(a-1, c, b + c)
  f(n, 0, 1)
}

스트림 / 호프 사용

val fibStream:Stream[Int] = 0 #:: 1 #:: (fibStream zip fibStream.tail).map{ t => t._1 + t._2 }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.