ทำไมข้อมูลขนาดใหญ่จำเป็นต้องใช้งานได้?


9

ฉันเริ่มทำงานในโครงการใหม่ที่เกี่ยวข้องกับ Big Data สำหรับการฝึกงานของฉัน ผู้จัดการของฉันแนะนำให้เริ่มการเรียนรู้การเขียนโปรแกรมฟังก์ชั่น (พวกเขาขอแนะนำสกาล่า) ฉันมีประสบการณ์ที่ต่ำต้อยโดยใช้ F # แต่ฉันไม่เห็นความสำคัญของการใช้กระบวนทัศน์การเขียนโปรแกรมนี้เนื่องจากมีราคาแพงในบางกรณี

คณบดีพูดคุยเกี่ยวกับหัวข้อนี้ที่น่าสนใจและแบ่งปันความคิดของเขาว่าทำไม "Big Data" ที่นี่: http://www.youtube.com/watch?v=DFAdLCqDbLQ แต่มันไม่สะดวกเพราะ Big Data ไม่ได้แปล Hadoop เท่านั้น

ในฐานะที่เป็น BigData แนวคิดที่คลุมเครือมาก ฉันลืมไปซักพักแล้ว ฉันพยายามหาตัวอย่างง่ายๆหนึ่งตัวอย่างเพื่อเปรียบเทียบระหว่างแง่มุมต่าง ๆ เมื่อเราจัดการกับข้อมูลเพื่อดูว่าวิธีการใช้งานมีราคาแพงหรือไม่ หากการเขียนโปรแกรมเชิงฟังก์ชั่นมีราคาแพงและใช้หน่วยความจำสำหรับข้อมูลขนาดเล็กทำไมเราต้องใช้กับ Big Data?

นอกเหนือจากเครื่องมือแฟนซีฉันพยายามสร้างวิธีแก้ปัญหาสำหรับปัญหาเฉพาะและเป็นที่นิยมโดยใช้สามวิธีคือวิธีที่จำเป็นและวิธีการใช้งาน (การเรียกซ้ำโดยใช้คอลเลกชัน) ฉันเปรียบเทียบเวลาและความซับซ้อนเพื่อเปรียบเทียบระหว่างสามแนวทาง

ฉันใช้ Scala เพื่อเขียนฟังก์ชันเหล่านี้เนื่องจากเป็นเครื่องมือที่ดีที่สุดในการเขียนอัลกอริทึมโดยใช้กระบวนทัศน์สามแบบ

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
}

ฉันสังเกตเห็นว่าการเขียนโปรแกรมฟังก์ชั่นหนัก! ใช้เวลานานและใช้พื้นที่ในหน่วยความจำมากขึ้น ฉันสับสนเมื่อใดก็ตามที่ฉันอ่านบทความหรือดูการพูดคุยพวกเขาบอกว่าเราควรใช้การเขียนโปรแกรมการทำงานในด้านวิทยาศาสตร์ข้อมูล จริงมันง่ายขึ้นและมีประสิทธิภาพมากขึ้นโดยเฉพาะในโลกของข้อมูล แต่มันต้องใช้เวลามากขึ้นและใช้พื้นที่หน่วยความจำมากขึ้น

ดังนั้นทำไมเราต้องใช้ฟังก์ชั่นการเขียนโปรแกรมใน Big Data? แนวทางปฏิบัติที่ดีที่สุดในการใช้ฟังก์ชั่นการเขียนโปรแกรม (Scala) สำหรับ Big Data คืออะไร?


5
ฟังก์ชั่นการเขียนโปรแกรมทำให้ง่ายต่อการขนานรหัสของคุณดังนั้นแม้ว่าการดำเนินการเดียวอาจใช้เวลามากขึ้นในการทำงานในหัวข้อเดียวประสิทธิภาพโดยรวมได้ดีขึ้นเนื่องจากการขนาน
Giorgio

@Giorgio: มีกระบวนทัศน์ที่แตกต่างกันในฐานะนักแสดงแบบจำลองเพื่อให้ได้ประสิทธิภาพที่ดีที่สุดในการขนาน ไม่คิดอย่างนั้นเหรอ
user3047512

2
ฉันเดาว่ามันเป็นเพราะแผนที่ / ลดแนวทางจาก hadoop เป็นแนวคิดจากการเขียนโปรแกรมการทำงาน
Doc Brown

1
@ user3047512: ตัวอย่างเช่น Erlang ใช้โมเดลนักแสดงและเป็นส่วนที่ใช้งานได้ดีที่สุด
Giorgio

2
การเชื่อมต่อระหว่าง "ข้อมูลขนาดใหญ่" แฟชั่นและ FP นั้นไม่ตรงไปตรงมา ใน "ข้อมูลขนาดใหญ่" วิธีการลดขนาดแผนที่เรียกว่าทันสมัยซึ่งในทางกลับกันก็ได้รับแรงบันดาลใจจากจรรยาบรรณการทำงานของโปรแกรม นี่คือที่ความคล้ายคลึงกันสิ้นสุดลงฉันไม่สามารถมองเห็นการเชื่อมต่อระหว่างโลกทั้งสองนี้ได้อีก
SK-logic

คำตอบ:


13

นี่คือวิธีที่ฉันเห็น:

  • ลองเพิกเฉยคำว่า "ข้อมูลขนาดใหญ่" ซักพักเพราะมันเป็นแนวคิดที่คลุมเครือ

  • คุณพูดถึง Hadoop Hadoop ทำ 2 สิ่ง: ช่วยให้คุณมีไดรฟ์ "เสมือน" ซึ่งกระจายอยู่ในหลาย ๆ เครื่องพร้อมความซ้ำซ้อนซึ่งสามารถเข้าถึงได้ผ่าน API ของ Hadoop ราวกับว่าเป็นไดรฟ์เดียวที่รวมกัน มันเรียกว่า HDFS เช่นเดียวกับในHadoop Distributed File System อีกอย่างที่ Hadoop ทำคืออนุญาตให้คุณเรียกใช้งาน Map-Reduce (เป็นกรอบสำหรับ Map-Reduce) หากเราตรวจสอบหน้า Wikipedia ของ MapReduceเราจะเห็นว่า:

MapReduce เป็นรูปแบบการเขียนโปรแกรมสำหรับการประมวลผลชุดข้อมูลขนาดใหญ่ที่มีอัลกอริทึมแบบขนานกระจายในคลัสเตอร์

...

โปรแกรม MapReduce ประกอบด้วยขั้นตอน Map () ที่ดำเนินการกรองและเรียงลำดับ (เช่นการเรียงลำดับนักเรียนตามชื่อในคิวหนึ่งคิวสำหรับแต่ละชื่อ) และกระบวนการลด () ที่ดำเนินการสรุป (เช่นการนับจำนวน ของนักเรียนในแต่ละคิวให้ความถี่ชื่อ)

...

'MapReduce' เป็นกรอบสำหรับการประมวลผลปัญหาแบบขนานได้ในชุดข้อมูลขนาดใหญ่โดยใช้คอมพิวเตอร์จำนวนมาก

นอกจากนี้ในหน้านี้ Hadoop ก็อธิบายว่า

Hadoop การใช้งาน MapReduce ของ Apache และโอเพนซอร์สฟรี

ตอนนี้ Hadoop เขียนด้วยภาษาจาวาซึ่งไม่ใช่ภาษาที่ใช้งานได้ นอกจากนี้ถ้าเรามองในหน้า Hadoop ของเรายังได้พบกับตัวอย่างของวิธีการสร้างงาน MapReduce ในชวาและปรับใช้ในคลัสเตอร์

นี่คือตัวอย่าง Java ของงาน Fibonnaci MapReduce สำหรับ Hadoop

ฉันหวังว่านี่จะตอบคำถามของคุณคือ BigData และโดยเฉพาะอย่างยิ่งงาน MapReduce ที่สร้างจาก Fibonacci ไม่ "ต้องการ" เพื่อใช้งานได้หรือคุณสามารถนำไปใช้ในภาษา OO ได้หากคุณต้องการ (เช่น)

แน่นอนว่านั่นไม่ได้หมายความว่า BigData "ต้องการ" เป็น OO เท่านั้น คุณสามารถใช้ภาษาที่ใช้งานได้ดีในการใช้งาน MapReduce เช่นงาน คุณสามารถยกตัวอย่างเช่นใช้ Scala กับ Hadoop ถ้าคุณต้องการที่จะผ่านการลวก

ประเด็นอื่นที่ฉันคิดว่าน่าพูดถึง

เมื่อทำ recursion ใน Scala ถ้ารหัสของคุณช่วยให้มัน Scala จะทำหางเรียกร้องการเพิ่มประสิทธิภาพ อย่างไรก็ตามตั้งแต่JVM ที่ไม่ได้ (ยัง) สนับสนุนหางโทรเพิ่มประสิทธิภาพ , Scala นี้ประสบความสำเร็จโดยการเปลี่ยนที่รวบรวมเวลาโทร recursive ของคุณด้วยรหัสเทียบเท่ากับลูปตามที่อธิบายไว้ที่นี่ สิ่งนี้โดยทั่วไปหมายถึงว่าการทำเกณฑ์มาตรฐานเทียบกับแบบไม่เรียกซ้ำแบบเรียกซ้ำโดยใช้ Scala นั้นไม่มีจุดหมายเพราะทั้งคู่ต่างก็ทำสิ่งเดียวกันในเวลาทำงาน


2
คุณสร้างจุดยอดเยี่ยมเกี่ยวกับ JVM ที่ไม่สนับสนุนการปรับแต่งการโทรแบบหางซึ่งจะทำลายมาตรฐานที่เสนอโดย OP นี่เป็นคำตอบที่ให้ข้อมูลมากขอบคุณ
maple_shaft

1
ขอบคุณสำหรับคำตอบใช่! tail-call-optimization เป็นหนึ่งในคุณสมบัติการสแกนที่ซ่อนอยู่ stackoverflow.com/questions/1025181/hidden-features-of-scala/... หนึ่งในปัญหาของ "Big Data" คือทุก บริษัท พยายามที่จะสร้างเทคโนโลยีใหม่ในวิธีที่ต่างกัน แต่มีสองหลัก: Hadoop เทคโนโลยีและอื่น ๆ ดังที่คุณกล่าวว่ามันเป็นเรื่องส่วนตัวและเกี่ยวข้องกับปัญหาที่เกิดขึ้นด้วยตนเองเราควรเลือกกระบวนทัศน์การเขียนโปรแกรมที่ถูกต้องตามความเชี่ยวชาญของเราเช่นกัน ตัวอย่างเช่น: โมเดลการทำนายตามเวลาจริงทำงานได้ไม่ดีบนแพลตฟอร์ม Hadoop
user3047512

9

ตราบใดที่คุณสามารถเรียกใช้บนเครื่องเดียวไม่ใช่ "ข้อมูลขนาดใหญ่" ปัญหาตัวอย่างของคุณไม่เหมาะสมอย่างยิ่งที่จะแสดงอะไรเกี่ยวกับเรื่องนี้

ข้อมูลขนาดใหญ่หมายความว่าขนาดของปัญหาใหญ่เกินไปที่การกระจายการประมวลผลไม่ใช่การเพิ่มประสิทธิภาพ แต่เป็นข้อกำหนดขั้นพื้นฐาน และฟังก์ชั่นการเขียนโปรแกรมช่วยให้การเขียนรหัสการกระจายที่ถูกต้องและมีประสิทธิภาพง่ายขึ้นเนื่องจากโครงสร้างข้อมูลและไร้สัญชาติที่ไม่เปลี่ยนแปลง


"ข้อมูลขนาดใหญ่หมายความว่าขนาดของปัญหาใหญ่เกินไปที่การกระจายการประมวลผลไม่ใช่การเพิ่มประสิทธิภาพ แต่เป็นข้อกำหนดขั้นพื้นฐาน" - ฉันไม่เข้าใจปัญหาประเภทใดที่ไม่สามารถแก้ไขได้ทั้งหมดโดยใช้หนึ่งเครื่องและต้องการอย่างน้อย N ที่ N> 1 ...
Shivan Dragon

6
@ShivanDragon: ประเภทของปัญหาที่มีข้อกำหนดด้านประสิทธิภาพที่เป็นไปไม่ได้อย่างสมบูรณ์ในระบบเดียว หรือที่ขนาดข้อมูลมีขนาดใหญ่จนไม่มีระบบเดียวที่สามารถจัดเก็บได้ทั้งหมด
Michael Borgwardt

ฉันขอโทษที่ฉันเห็นจุดของคุณตอนนี้ ถูกต้องหรือไม่ที่จะบอกว่าสิ่งที่คุณพูดถึงคือโดยเฉพาะอย่างยิ่ง MapReduce ที่มีชีวิตอยู่ใต้ร่มของ BigData?
Shivan Dragon

ขอบคุณสำหรับข้อมูลของคุณฉันเห็นด้วย บางทีฉันอาจไม่พบตัวอย่างง่ายๆที่ดีในการสาธิตมุมมองของฉัน "Big Data" ยังคงเป็นวิธีที่นักพัฒนาใช้ข้อมูลในการแก้ปัญหาประจำวันของเราโดยคำนึงถึงคำจำกัดความของ 3V ฉันจะลืม 3V ไปสักพักแล้วพูดถึงแง่มุมที่เรียบง่ายมากในการจัดการกับข้อมูล หากเราเห็นว่าการวิเคราะห์ข้อมูลในแบบที่ใช้งานได้มีราคาแพงทำไมเราถึงพูดว่า "ข้อมูลขนาดใหญ่" จำเป็นต้องใช้งานได้? นี่คือจุดของฉัน
user3047512

4
@ShivanDragon ตัวอย่างเช่น LHC คือการผลิตหลายกิกะไบต์ของข้อมูลต่อวินาที ไม่แน่ใจว่าเครื่องเดียวสามารถจัดการกับปริมาณงานได้หรือไม่
SK-logic

4

ฉันไม่ทราบว่าสกาล่าดังนั้นฉันไม่สามารถแสดงความคิดเห็นเกี่ยวกับวิธีการทำงานของคุณได้ แต่รหัสของคุณดูเหมือน overkill

ฟังก์ชั่นวนซ้ำของคุณในอีกทางหนึ่งนั้นไม่มีประสิทธิภาพ เนื่องจากฟังก์ชั่นเรียกตัวเองสองครั้งมันเป็นลำดับ 2 ^ n ซึ่งไม่มีประสิทธิภาพสูง หากคุณต้องการเปรียบเทียบทั้งสามวิธีคุณต้องเปรียบเทียบการปรับใช้ที่เหมาะสมสามแบบ

ฟังก์ชัน Fibonacci สามารถใช้งานซ้ำโดยเรียกฟังก์ชันเพียงครั้งเดียว เรามานิยามนิยามที่กว้างกว่า

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);
}

ขอบคุณ! คุณยกประเด็นที่ดี แต่ไม่มีวิธีที่มีประสิทธิภาพในการทำซ้ำ นี่เป็นปัญหาที่พบบ่อยมาก (Fibonacci suite) และนี่คือประเด็นของการแก้ปัญหาเดียวกันโดยใช้สามวิธี คุณช่วยแนะนำวิธีที่ดีกว่าในการแก้ปัญหานี้ด้วยภาษาการเขียนโปรแกรมฉันสามารถเขียนใหม่โดยใช้ scala และทำแบบทดสอบเดียวกันได้หรือไม่?
user3047512

@ user3047512 สำหรับภาษาที่รองรับการเรียกซ้ำหางคุณสามารถเขียนมันด้วยแอคคูมูเลเตอร์ ตัวอย่าง
toasted_flakes

Scala ยังสนับสนุนการเรียกซ้ำแบบหางเป็นคุณลักษณะที่ซ่อนอยู่oldfashionedsoftware.com/2008/09/27/…
3047512

1
@ user3047512 เนื่องจากโซลูชันแบบเรียกซ้ำเป็นฟังก์ชันบริสุทธิ์ (เอาต์พุตขึ้นอยู่กับฟังก์ชัน args และไม่มีสิ่งอื่นใด ) การบันทึกจึงเป็นวิธีที่ดี ใส่อย่างง่าย ๆ ทุกครั้งที่มันคืนค่าเก็บ args และส่งผลให้เกิดการแฮชคีย์ / ค่าและทุกครั้งที่มีการเรียกใช้ฟังก์ชันให้ดูที่นั่นก่อน นี่คือหนึ่งในข้อดีของฟังก์ชั่นแท้ ๆ การเรียกใช้ฟังก์ชันนี้ในอนาคตจะพบค่าแฮชที่มีมาก่อนและทำการคำนวณที่ไม่มีศูนย์เพราะเรารู้ว่าผลลัพธ์จะไม่เปลี่ยนแปลง
Izkata

@ user3047512 เวอร์ชันซ้ำยังดูเหมือนว่าเป็นฟังก์ชั่นที่บริสุทธิ์ในกรณีนี้ แต่นั่นไม่ได้เป็นจริงเสมอไป - ในภาษาที่ใช้งานได้ฉันเชื่อว่ามันบังคับใช้โดยภาษาที่ดีกว่า ...
Izkata

0

หากการเขียนโปรแกรมเชิงฟังก์ชั่นมีราคาแพงและใช้หน่วยความจำสำหรับข้อมูลขนาดเล็กทำไมเราต้องใช้กับ Big Data?

โดยเฉพาะฉันสามารถเห็นแอปพลิเคชั่นบางตัวที่มีประโยชน์มาก อดีต สถิติคือการคำนวณฟังก์ชั่นเกาส์เซียนในทันทีด้วยพารามิเตอร์ที่แตกต่างกันหรือชุดของพารามิเตอร์สำหรับการวิเคราะห์ข้อมูล นอกจากนี้ยังมีการแก้ไขสำหรับการวิเคราะห์เชิงตัวเลข ฯลฯ

แนวทางปฏิบัติที่ดีที่สุดในการใช้ฟังก์ชั่นการเขียนโปรแกรม (Scala) สำหรับ Big Data คืออะไร?

เพื่อตอบคำถามเกี่ยวกับประสิทธิภาพนอกจากนี้ยังมีเทคนิคที่ช่วยเพิ่มประสิทธิภาพของคุณในพื้นที่หรือเวลาโดยเฉพาะการเรียกซ้ำ, การเรียกซ้ำแบบหาง , การส่งต่อแบบต่อเนื่อง , ฟังก์ชันการเรียงลำดับที่สูงขึ้นฯลฯ บางภาษามีข้อดีและข้อเสีย สิ่งที่ง่ายเหมือนลำดับ Fibonnacci ฉันอาจใช้วิธีที่จำเป็นตามที่ฉันพบในบางครั้งเพื่อนร่วมงานของฉันลังเลและอาจไม่สะดวกกับการเขียนโปรแกรมที่ใช้งานได้และใช้เวลาในการพัฒนามากขึ้น ... (ฉันยังต้องการ ใช้การเขียนโปรแกรมใช้งานได้เมื่อฉันสามารถ [แอปพลิเคชันที่ฉันรับผิดชอบ]) เนื่องจากฉันพบว่ามันรวดเร็วสะอาดและ "อ่านง่าย" (แม้ว่าฉันจะพบรหัสส่วนตัว)

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)
}

การใช้สตรีม / hof

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.