Penjelasan sederhana dari MapReduce?

166

Terkait dengan pertanyaan CouchDB saya .

Adakah yang bisa menjelaskan MapReduce dalam hal yang bisa dimengerti oleh seorang numbnuts?

reefnet_alex
sumber
3
Dan inilah pendapat saya: MapReduce untuk dan bersama anak-anak .
Michael Hausenblas
@MichaelHausenblas - Saya suka teladan Anda: mudah dimengerti dan menyenangkan bagi seluruh keluarga.
Lee
Joel Spolsky memiliki penjelasan yang bagus untuk pemula - joelonsoftware.com/items/2006/08/01.html
user2314737

Jawaban:

187

Turun ke dasar untuk Peta dan Mengurangi.


Peta adalah fungsi yang "mengubah" item dalam beberapa jenis daftar ke jenis lain dan mengembalikannya ke jenis daftar yang sama.

misalkan saya memiliki daftar angka: [1,2,3] dan saya ingin menggandakan setiap angka, dalam hal ini, fungsi untuk "menggandakan setiap angka" adalah fungsi x = x * 2. Dan tanpa pemetaan, saya bisa menulis loop sederhana, katakanlah

A = [1, 2, 3]
foreach (item in A) A[item] = A[item] * 2

dan saya akan memiliki A = [2, 4, 6] tetapi alih-alih menulis loop, jika saya memiliki fungsi peta saya bisa menulis

A = [1, 2, 3].Map(x => x * 2)

x => x * 2 adalah fungsi yang akan dieksekusi terhadap elemen dalam [1,2,3]. Apa yang terjadi adalah program mengambil setiap item, mengeksekusi (x => x * 2) terhadapnya dengan membuat x sama dengan setiap item, dan menghasilkan daftar hasil.

1 : 1 => 1 * 2 : 2  
2 : 2 => 2 * 2 : 4  
3 : 3 => 3 * 2 : 6  

jadi setelah menjalankan fungsi peta dengan (x => x * 2) Anda akan memiliki [2, 4, 6].


Reduce adalah fungsi yang "mengumpulkan" item dalam daftar dan melakukan beberapa perhitungan pada semuanya , sehingga menguranginya menjadi nilai tunggal.

Menemukan jumlah atau menemukan rata-rata adalah contoh dari fungsi pengurangan. Seperti jika Anda memiliki daftar angka, ucapkan [7, 8, 9] dan Anda ingin disimpulkan, Anda akan menulis satu lingkaran seperti ini

A = [7, 8, 9]
sum = 0
foreach (item in A) sum = sum + A[item]

Tetapi, jika Anda memiliki akses ke fungsi pengurangan, Anda bisa menulisnya seperti ini

A = [7, 8, 9]
sum = A.reduce( 0, (x, y) => x + y )

Sekarang agak membingungkan mengapa ada 2 argumen (0 dan fungsi dengan x dan y) dilewati. Agar fungsi pengurangan bermanfaat, ia harus dapat mengambil 2 item, menghitung sesuatu dan "mengurangi" 2 item menjadi hanya satu nilai tunggal, sehingga program dapat mengurangi setiap pasangan hingga kami memiliki nilai tunggal.

eksekusi akan mengikuti:

result = 0
7 : result = result + 7 = 0 + 7 = 7
8 : result = result + 8 = 7 + 8 = 15
9 : result = result + 9 = 15 + 9 = 24

Tetapi Anda tidak ingin memulai dengan nol setiap saat, jadi argumen pertama ada untuk membiarkan Anda menentukan nilai seed khususnya nilai di result =baris pertama .

katakanlah Anda ingin menjumlahkan 2 daftar, mungkin terlihat seperti ini:

A = [7, 8, 9]
B = [1, 2, 3]
sum = 0
sum = A.reduce( sum, (x, y) => x + y )
sum = B.reduce( sum, (x, y) => x + y )

atau versi yang lebih mungkin Anda temukan di dunia nyata:

A = [7, 8, 9]
B = [1, 2, 3]

sum_func = (x, y) => x + y
sum = A.reduce( B.reduce( 0, sum_func ), sum_func )

Merupakan hal yang baik dalam perangkat lunak DB karena, dengan dukungan Map \ Reduce Anda dapat bekerja dengan database tanpa perlu tahu bagaimana data disimpan dalam DB untuk menggunakannya, itulah gunanya mesin DB.

Anda hanya perlu dapat "memberi tahu" mesin apa yang Anda inginkan dengan memasok mereka dengan fungsi Peta atau Mengurangi dan kemudian mesin DB dapat menemukan jalannya di sekitar data, menerapkan fungsi Anda, dan menghasilkan hasil yang Anda inginkan. ingin semua tanpa Anda tahu bagaimana itu melingkupi semua catatan.

Ada indeks dan kunci serta gabungan dan tampilan serta banyak hal yang dapat disimpan oleh satu database, jadi dengan melindungi Anda dari bagaimana data sebenarnya disimpan, kode Anda dibuat lebih mudah untuk ditulis dan dipelihara.

Hal yang sama berlaku untuk pemrograman paralel, jika Anda hanya menentukan apa yang ingin Anda lakukan dengan data alih-alih benar-benar menerapkan kode pengulangan, maka infrastruktur yang mendasarinya bisa "memparalelkan" dan menjalankan fungsi Anda dalam pengulangan paralel simultan untuk Anda.

chakrit
sumber
Ok, saya mengerti peta dan mengurangi diambil secara individual. Tapi aplikasi apa yang bisa saya miliki untuk mengurangi? Dalam skenario Google, apakah mereka akan menggunakannya misalnya untuk menjumlahkan serangkaian parameter yang memberi mereka peringkat halaman untuk kata kunci yang diberikan?
Lorenzo
@ lbolognini var total = orderesum .um (o => o.UnitPrice * o.Quantity)
chakrit
@ lbolognini Ada banyak kegunaan ketika Anda abstrak konsep perulangan. Dalam skenario Google, mereka mungkin memiliki 1000 mesin untuk menghitung pagerank, tautan, dan yang lainnya. Apa yang mereka lakukan ketika mereka perlu menambahkan beberapa server lagi? Mengubah setiap kode perulangan mungkin bukan opsi. Jadi yang mereka lakukan adalah mereka menulis kode perhitungan mereka terhadap fungsi "Reduce" ... Dan ketika daftar server berubah, hanya fungsi "Reduce" yang perlu diubah. Mengerti?
chakrit
bagaimana mengurangi rata-rata menghitung? dari apa yang saya lihat saya kira Anda tidak bisa? mungkin memetakan pembilang dan penyebut dan membagi pada akhir penjumlahan keduanya?
andyczerwonka
@arcticpenguin Saya menjadi agak terlalu umum di sana Sebenarnya Average()seharusnya icing di atas Sum(). Tapi saya membicarakannya untuk menggambarkan mengapa fungsi ini disebut "Reduce" ... Fungsi rata-rata adalah sesuatu yang mengambil daftar angka dan menguranginya menjadi satu nomor (yang merupakan rata-rata).
chakrit
60

MapReduce adalah metode untuk memproses sejumlah besar data secara paralel tanpa mengharuskan pengembang untuk menulis kode lain selain mapper dan mengurangi fungsi.

Fungsi peta mengambil data dan menghasilkan hasilnya, yang disimpan dalam penghalang. Fungsi ini dapat berjalan secara paralel dengan sejumlah besar tugas peta yang sama . Dataset kemudian dapat dikurangi menjadi nilai skalar.

Jadi jika Anda menganggapnya seperti pernyataan SQL

SELECT SUM(salary)
FROM employees
WHERE salary > 1000
GROUP by deptname

Kita dapat menggunakan peta untuk mendapatkan subset karyawan kami dengan gaji> 1000 yang dipetakan ke penghalang ke dalam ember ukuran grup.

Reduce akan menjumlahkan masing-masing kelompok tersebut. Memberi Anda set hasil Anda.

baru saja memetik ini dari catatan studi universitas saya dari kertas google

Johnno Nolan
sumber
33
  1. Ambil banyak data
  2. Lakukan semacam transformasi yang mengubah setiap datum ke jenis datum lain
  3. Gabungkan data baru itu menjadi data yang lebih sederhana

Langkah 2 adalah Peta. Langkah 3 adalah Mengurangi.

Sebagai contoh,

  1. Dapatkan waktu antara dua impuls pada sepasang meter tekanan di jalan
  2. Petakan waktu-waktu tersebut dalam kecepatan berdasarkan jarak meter
  3. Kurangi kecepatan itu ke kecepatan rata-rata

Alasan MapReduce terbagi antara Map dan Reduce adalah karena bagian yang berbeda dapat dengan mudah dilakukan secara paralel. (Terutama jika Reduce memiliki sifat matematika tertentu.)

Untuk deskripsi MapReduce yang kompleks namun bagus, lihat: Model Pemrograman MapReduce Google - Revisited (PDF) .

Frank Krueger
sumber
1
Saya akan mengatakan untuk langkah 3, "gabungkan" alih-alih "transformasi"
TraumaPony
Pertama kali, tiga jawaban yang digabungkan adalah jawaban TERBAIK. Baca dulu tautan artikel Nasser (level teoritis). Lalu jawaban chakrit (penjelasan individual tentang pengurangan peta). Sekarang jawaban Frank (Apa idiom MapReduce yang terkenal itu). Terima kasih untuk kalian bertiga. :)
Ajeet Ganga
20

MAP dan REDUCE adalah fungsi lama Lisp dari masa ketika manusia membunuh dinosaurus terakhir.

Bayangkan Anda memiliki daftar kota dengan informasi tentang nama, jumlah orang yang tinggal di sana dan ukuran kota:

(defparameter *cities*
  '((a :people 100000 :size 200)
    (b :people 200000 :size 300)
    (c :people 150000 :size 210)))

Sekarang Anda mungkin ingin menemukan kota dengan kepadatan penduduk tertinggi.

Pertama kita membuat daftar nama kota dan kepadatan populasi menggunakan MAP:

(map 'list
     (lambda (city)
         (list (first city)
               (/ (getf (rest city) :people)
                  (getf (rest city) :size))))
     *cities*)

=>   ((A 500) (B 2000/3) (C 5000/7))

Menggunakan REDUCE sekarang kita dapat menemukan kota dengan kepadatan populasi terbesar.

(reduce (lambda (a b)
          (if (> (second a) (second b))
             a
             b))
        '((A 500) (B 2000/3) (C 5000/7)))

 =>   (C 5000/7)

Menggabungkan kedua bagian kita mendapatkan kode berikut:

(reduce (lambda (a b)
          (if (> (second a) (second b))
             a
             b))
        (map 'list
             (lambda (city)
                (list (first city)
                   (/ (getf (rest city) :people)
                      (getf (rest city) :size))))
             *cities*))

Mari kita kenalkan fungsi-fungsi:

(defun density (city)
   (list (first city)
         (/ (getf (rest city) :people)
            (getf (rest city) :size))))

(defun max-density (a b)
   (if (> (second a) (second b))
          a
          b))

Kemudian kita dapat menulis kode MAP REDUCE kita sebagai:

(reduce 'max-density
        (map 'list 'density *cities*))

 =>   (C 5000/7)

Itu panggilan MAPdan REDUCE(evaluasi itu dalam ke luar), sehingga disebut peta mengurangi .

Rainer Joswig
sumber
@MoMolog: fungsi MAX sudah ada dan melakukan sesuatu yang sedikit berbeda. Juga: orang tidak boleh mendefinisikan ulang MAX.
Rainer Joswig
max-densitymembandingkan elemen kedua dari argumen yang disahkan, kan? Maaf untuk hasil edit yang konyol.
Alexander Presber
@MoMolog: ya, itu adalah elemen kedua dan itu hanya berguna dalam konteks contoh kecil ini. Kode ini juga sengaja ditulis dalam Lisp gaya lama dengan daftar sebagai struktur data ...
Rainer Joswig
17

Mari kita ambil contoh dari makalah Google . Tujuan MapReduce adalah untuk dapat menggunakan secara efisien sejumlah unit pemrosesan yang bekerja secara paralel untuk beberapa jenis algoritma. Contohnya adalah sebagai berikut: Anda ingin mengekstrak semua kata dan jumlah mereka dalam satu set dokumen.

Implementasi yang khas:

for each document
    for each word in the document
        get the counter associated to the word for the document
        increment that counter 
    end for
end for

Implementasi MapReduce:

Map phase (input: document key, document)
for each word in the document
    emit an event with the word as the key and the value "1"
end for

Reduce phase (input: key (a word), an iterator going through the emitted values)
for each value in the iterator
    sum up the value in a counter
end for

Di sekitar itu, Anda akan memiliki program master yang akan mempartisi set dokumen dalam "splits" yang akan ditangani secara paralel untuk fase Peta. Nilai-nilai yang dipancarkan ditulis oleh pekerja dalam buffer khusus untuk pekerja. Program master kemudian mendelegasikan pekerja lain untuk melakukan fase Reduce segera setelah diberitahu bahwa buffer siap untuk ditangani.

Setiap output pekerja (menjadi Peta atau pekerja Reduce) sebenarnya adalah file yang disimpan pada sistem file terdistribusi (GFS untuk Google) atau dalam database terdistribusi untuk CouchDB.

Damien B
sumber
10

Pengenalan yang sangat mudah , cepat dan "untuk boneka" untuk MapReduce tersedia di: http://www.marcolotz.com/?p=67

Posting beberapa kontennya:

Pertama-tama, mengapa MapReduce awalnya dibuat?

Pada dasarnya Google membutuhkan solusi untuk membuat pekerjaan komputasi besar dengan mudah dapat diparalelkan, memungkinkan data untuk didistribusikan di sejumlah mesin yang terhubung melalui jaringan. Selain itu, ia harus menangani kegagalan alat berat secara transparan dan mengelola masalah penyeimbangan muatan.

Apa kekuatan sejati MapReduce?

Orang mungkin mengatakan bahwa sihir MapReduce didasarkan pada aplikasi Map and Reduce functions. Saya harus mengaku sobat, bahwa saya sangat tidak setuju. Fitur utama yang membuat MapReduce begitu populer adalah kemampuannya untuk paralelisasi dan distribusi otomatis, dikombinasikan dengan antarmuka yang sederhana. Faktor-faktor ini disimpulkan dengan penanganan kegagalan transparan untuk sebagian besar kesalahan membuat kerangka kerja ini sangat populer.

Sedikit lebih dalam di atas kertas:

MapReduce pada awalnya disebutkan dalam makalah Google (Dean & Ghemawat, 2004 - tautan di sini) sebagai solusi untuk membuat perhitungan dalam Big Data menggunakan pendekatan paralel dan klaster komoditas-komputer. Berbeda dengan Hadoop, yang ditulis dalam Java, kerangka kerja Google ditulis dalam C ++. Dokumen tersebut menjelaskan bagaimana kerangka kerja paralel akan berperilaku menggunakan fungsi Map and Reduce dari pemrograman fungsional pada set data yang besar.

Dalam solusi ini akan ada dua langkah utama - disebut Map and Reduce -, dengan langkah opsional antara yang pertama dan yang kedua - yang disebut Combine. Langkah Peta akan berjalan terlebih dahulu, melakukan perhitungan dalam pasangan nilai kunci input dan menghasilkan nilai kunci output baru. Kita harus ingat bahwa format pasangan nilai kunci input tidak perlu sama dengan pasangan format output. Langkah Reduce akan mengumpulkan semua nilai dari kunci yang sama, melakukan perhitungan lain di atasnya. Sebagai hasilnya, langkah terakhir ini akan menampilkan pasangan nilai kunci. Salah satu aplikasi MapReduce yang paling sepele adalah menerapkan jumlah kata.

Kode semu untuk aplikasi ini, diberikan di bawah ini:

map(String key, String value):

// key: document name
// value: document contents
for each word w in value:
EmitIntermediate(w, “1”);

reduce(String key, Iterator values):

// key: a word
// values: a list of counts
int result = 0;
for each v in values:
    result += ParseInt(v);
Emit(AsString(result));

Seperti yang dapat dilihat, peta membaca semua kata dalam catatan (dalam hal ini catatan dapat berupa garis) dan memancarkan kata sebagai kunci dan angka 1 sebagai nilai. Kemudian, pengurangan akan mengelompokkan semua nilai dari kunci yang sama. Mari kita beri contoh: bayangkan bahwa kata 'rumah' muncul tiga kali dalam catatan. Input dari peredam adalah [rumah, [1,1,1]]. Dalam peredam, itu akan menjumlahkan semua nilai untuk rumah kunci dan memberikan sebagai output nilai kunci berikut: [rumah, [3]].

Berikut adalah gambar bagaimana ini akan terlihat dalam kerangka MapReduce:

Gambar dari kertas Google MapReduce Asli

Sebagai beberapa contoh klasik aplikasi MapReduce lainnya, dapat dikatakan:

• Hitungan frekuensi akses URL

• Membalik Grafik Tautan Web

• Grep Terdistribusi

• Istilah Vektor per host

Untuk menghindari terlalu banyak lalu lintas jaringan, makalah ini menjelaskan bagaimana kerangka kerja harus mencoba untuk mempertahankan lokalitas data. Ini berarti bahwa itu harus selalu berusaha untuk memastikan bahwa mesin yang menjalankan pekerjaan Peta memiliki data dalam memori / penyimpanan lokal, menghindari mengambilnya dari jaringan. Bertujuan untuk mengurangi jaringan melalui put mapper, langkah penggabung opsional, dijelaskan sebelumnya, digunakan. Combiner melakukan perhitungan pada output dari pemetaan di mesin yang diberikan sebelum mengirimnya ke Reduksi - yang mungkin di mesin lain.

Dokumen tersebut juga menjelaskan bagaimana elemen-elemen kerangka kerja harus berperilaku jika terjadi kesalahan. Elemen-elemen ini, di koran, disebut sebagai pekerja dan tuan. Mereka akan dibagi menjadi elemen yang lebih spesifik dalam implementasi open-source. Karena Google hanya menggambarkan pendekatan dalam makalah dan tidak merilis perangkat lunak berpemilik, banyak kerangka kerja open-source dibuat untuk mengimplementasikan model. Sebagai contoh orang dapat mengatakan Hadoop atau fitur MapReduce terbatas di MongoDB.

Run-time harus menangani rincian programmer yang tidak ahli, seperti mempartisi data input, menjadwalkan eksekusi program di seluruh set mesin yang besar, menangani kegagalan mesin (dengan cara yang transparan, tentu saja) dan mengelola komunikasi antar-mesin . Pengguna yang berpengalaman dapat mengatur parameter ini, seperti bagaimana data input akan dipartisi antar pekerja.

Konsep Kunci:

Toleransi Kesalahan:Itu harus mentolerir kegagalan mesin dengan anggun. Untuk melakukan hal ini, master mengirim pekerja secara berkala. Jika master tidak menerima tanggapan dari pekerja tertentu dalam selang waktu tertentu, master akan mendefinisikan pekerjaan sebagai gagal pada pekerja tersebut. Dalam hal ini, semua tugas peta yang diselesaikan oleh pekerja yang salah dibuang dan diberikan kepada pekerja lain yang tersedia. Hal serupa terjadi jika pekerja masih memproses peta atau mengurangi tugas. Perhatikan bahwa jika pekerja sudah menyelesaikan pengurangan bagiannya, semua perhitungan sudah selesai pada saat itu gagal dan tidak perlu diatur ulang. Sebagai titik kegagalan utama, jika master gagal, semua pekerjaan gagal. Untuk alasan ini, seseorang dapat menentukan pos pemeriksaan berkala untuk master, untuk menyimpan struktur datanya.

Lokalitas: Untuk menghindari lalu lintas jaringan, kerangka kerja mencoba memastikan bahwa semua data input tersedia secara lokal untuk mesin yang akan melakukan perhitungan pada mereka. Dalam uraian asli, ia menggunakan Sistem File Google (GFS) dengan faktor replikasi diatur ke 3 dan ukuran blok 64 MB. Ini berarti bahwa blok yang sama dari 64 MB (yang menyusun file dalam sistem file) akan memiliki salinan yang sama di tiga mesin yang berbeda. Master tahu di mana blok-blok itu dan mencoba menjadwalkan pekerjaan peta di mesin itu. Jika gagal, master mencoba mengalokasikan mesin di dekat replika data input tugas (yaitu mesin pekerja di rak yang sama dengan mesin data).

Granularity Tugas: Dengan asumsi bahwa setiap fase peta dibagi menjadi potongan-potongan M dan bahwa setiap fase Mengurangi dibagi menjadi potongan-potongan R, idealnya adalah bahwa M dan R jauh lebih besar daripada jumlah mesin pekerja. Ini disebabkan fakta bahwa seorang pekerja yang melakukan banyak tugas berbeda meningkatkan penyeimbangan muatan dinamis. Selain itu, ini meningkatkan kecepatan pemulihan jika pekerja gagal (karena banyak tugas peta yang telah diselesaikan dapat tersebar di semua mesin lain).

Tugas Pencadangan: Kadang-kadang, pekerja Peta atau Peredam mungkin berperilaku jauh lebih lambat daripada yang lain di cluster. Ini dapat menahan total waktu pemrosesan dan membuatnya sama dengan waktu pemrosesan mesin lambat tunggal itu. Makalah asli menjelaskan alternatif yang disebut Tugas Cadangan, yang dijadwalkan oleh master ketika operasi MapReduce hampir selesai. Ini adalah tugas yang dijadwalkan oleh Master dari tugas yang sedang berlangsung. Dengan demikian, operasi MapReduce selesai ketika primer atau cadangan selesai.

Penghitung: Kadang-kadang seseorang mungkin ingin menghitung kejadian peristiwa. Karena alasan ini, dihitung di mana dibuat. Nilai-nilai konter dalam setiap pekerja secara berkala disebarkan ke master. Master kemudian mengumpulkan (Yap. Sepertinya agregator Pregel berasal dari tempat ini) nilai penghitung peta yang berhasil dan mengurangi tugas dan mengembalikannya ke kode pengguna ketika operasi MapReduce selesai. Ada juga nilai penghitung saat ini yang tersedia dalam status master, sehingga manusia yang menonton proses dapat melacak bagaimana perilakunya.

Yah, saya kira dengan semua konsep di atas, Hadoop akan menjadi kue untuk Anda. Jika Anda memiliki pertanyaan tentang artikel MapReduce asli atau apa pun yang terkait, beri tahu saya.

Prometheus
sumber
4

Saya tidak ingin terdengar basi, tetapi ini sangat membantu saya, dan itu sangat sederhana:

cat input | map | reduce > output
Mike Dewar
sumber
4

Jika Anda terbiasa dengan Python, berikut ini adalah penjelasan yang paling sederhana dari MapReduce:

In [2]: data = [1, 2, 3, 4, 5, 6]
In [3]: mapped_result = map(lambda x: x*2, data)

In [4]: mapped_result
Out[4]: [2, 4, 6, 8, 10, 12]

In [10]: final_result = reduce(lambda x, y: x+y, mapped_result)

In [11]: final_result
Out[11]: 42

Lihat bagaimana setiap segmen data mentah diproses secara individual, dalam hal ini, dikalikan dengan 2 (bagian peta dari MapReduce). Berdasarkan itu mapped_result, kami menyimpulkan bahwa hasilnya adalah 42( mengurangi bagian dari MapReduce).

Kesimpulan penting dari contoh ini adalah kenyataan bahwa setiap potongan pemrosesan tidak bergantung pada potongan lainnya. Misalnya, jika thread_1peta [1, 2, 3], dan thread_2peta [4, 5, 6], hasil akhirnya dari kedua utas masih akan [2, 4, 6, 8, 10, 12]tetapi kami telah membagi dua waktu pemrosesan untuk ini. Hal yang sama dapat dikatakan untuk operasi yang dikurangi dan merupakan inti dari bagaimana MapReduce bekerja dalam komputasi paralel.

Rafay
sumber