Giải thích đơn giản về MapReduce?


166

Liên quan đến CouchDB của tôi câu hỏi .

Bất cứ ai cũng có thể giải thích MapReduce theo cách mà một người tê có thể hiểu được?


4
Đây là thứ tốt nhất :) http://ksat.me/map-reduce-a-really-simple-int
sinhtion

3
Và đây là ý kiến ​​của tôi về nó: MapReduce cho và với những đứa trẻ .
Michael Hausenblas

@MichaelHausenblas - Tôi thích ví dụ của bạn: dễ hiểu và vui vẻ cho cả gia đình.
Lee

Joel Spolsky có một lời giải thích tốt cho người mới bắt đầu - joelonsoftware.com/items/2006/08/01.html
user2314737

Câu trả lời:


187

Đi tất cả các cách cơ bản cho Bản đồ và Giảm.


Bản đồ là một chức năng "biến đổi" các mục trong một loại danh sách thành một loại mục khác và đưa chúng trở lại trong cùng một loại danh sách.

giả sử tôi có một danh sách các số: [1,2,3] và tôi muốn nhân đôi mọi số, trong trường hợp này, hàm "nhân đôi mọi số" là hàm x = x * 2. Và không cần ánh xạ, tôi có thể viết một vòng lặp đơn giản, nói

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

và tôi có A = [2, 4, 6] nhưng thay vì viết các vòng lặp, nếu tôi có chức năng bản đồ, tôi có thể viết

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

x => x * 2 là một hàm được thực thi đối với các phần tử trong [1,2,3]. Điều gì xảy ra là chương trình lấy từng mục, thực hiện (x => x * 2) đối với nó bằng cách làm x bằng với từng mục và tạo danh sách kết quả.

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

vì vậy sau khi thực hiện chức năng bản đồ với (x => x * 2) bạn sẽ có [2, 4, 6].


Giảm là một hàm "thu thập" các mục trong danh sách và thực hiện một số tính toán trên tất cả chúng, do đó giảm chúng thành một giá trị duy nhất.

Tìm tổng hoặc tìm trung bình là tất cả các trường hợp của hàm giảm. Chẳng hạn như nếu bạn có một danh sách các số, giả sử [7, 8, 9] và bạn muốn chúng được tóm tắt, bạn sẽ viết một vòng lặp như thế này

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

Nhưng, nếu bạn có quyền truy cập vào hàm giảm, bạn có thể viết nó như thế này

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

Bây giờ có một chút khó hiểu tại sao có 2 đối số (0 và hàm có x và y) được truyền. Để hàm giảm có ích, nó phải có thể lấy 2 mục, tính toán một cái gì đó và "giảm" 2 mục đó xuống chỉ một giá trị, do đó chương trình có thể giảm mỗi cặp cho đến khi chúng ta có một giá trị duy nhất.

việc thực hiện sẽ như sau:

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

Nhưng bạn không muốn bắt đầu với số không mọi lúc, vì vậy đối số đầu tiên là ở đó để cho phép bạn chỉ định một giá trị hạt giống cụ thể là giá trị trong result =dòng đầu tiên .

nói rằng bạn muốn tổng hợp 2 danh sách, nó có thể trông như thế này:

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 )

hoặc một phiên bản bạn có thể tìm thấy nhiều hơn trong thế giới thực:

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

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

Đây là một điều tốt trong phần mềm DB bởi vì, với sự hỗ trợ của Map \ Giảm, bạn có thể làm việc với cơ sở dữ liệu mà không cần biết dữ liệu được lưu trữ trong DB để sử dụng nó như thế nào, đó là công cụ DB dùng để làm gì.

Bạn chỉ cần có thể "nói" cho động cơ những gì bạn muốn bằng cách cung cấp cho chúng chức năng Bản đồ hoặc Giảm và sau đó công cụ DB có thể tìm đường đi xung quanh dữ liệu, áp dụng chức năng của bạn và đưa ra kết quả cho bạn muốn tất cả mà không cần bạn biết làm thế nào nó lặp lại trên tất cả các hồ sơ.

Có các chỉ mục và khóa và tham gia và chế độ xem và rất nhiều nội dung mà một cơ sở dữ liệu có thể chứa, do đó, bằng cách bảo vệ bạn khỏi cách dữ liệu được lưu trữ thực sự, mã của bạn được viết và bảo trì dễ dàng hơn.

Tương tự như vậy đối với lập trình song song, nếu bạn chỉ xác định những gì bạn muốn làm với dữ liệu thay vì thực sự thực thi mã vòng lặp, thì cơ sở hạ tầng bên dưới có thể "song song" và thực hiện chức năng của bạn trong một vòng lặp song song đồng thời cho bạn.


Ok, tôi hiểu bản đồ và giảm lấy riêng lẻ. Nhưng những ứng dụng nào tôi có thể giảm? Trong một kịch bản Google, họ sẽ sử dụng nó làm ví dụ để tổng hợp một loạt các tham số cung cấp cho họ thứ hạng của một trang cho một từ khóa nhất định?
Lorenzo

@lbolognini var Total = orderes.Sum (o => o.Unitprice * o.Quantity)
chakrit

@lbolognini Có nhiều cách sử dụng khi bạn trừu tượng hóa chính khái niệm lặp. Trong kịch bản của Google, họ có thể có 1000 máy để tính toán máy nhắn tin, liên kết và không có gì. Họ làm gì khi cần thêm một vài máy chủ? Sửa đổi mỗi mã lặp đơn có lẽ không phải là một tùy chọn. Vì vậy, những gì họ đã làm là họ viết mã tính toán của họ dựa vào hàm "Giảm" thay vào đó ... Và khi danh sách máy chủ thay đổi, chỉ cần thay đổi chức năng "Giảm". Hiểu rồi?
chakrit

Làm thế nào để giảm tính toán trung bình? Từ những gì tôi thấy tôi đoán bạn không thể? có thể ánh xạ tử số và mẫu số và chia ở cuối của cả hai?
andyczerwonka

@arcticpenguin Tôi hơi quá chung chung ở đó. Trên thực tế Average()được cho là đóng băng trên đầu trang Sum(). Nhưng tôi đã nói về nó để minh họa tại sao hàm được gọi là "Giảm" ... Hàm trung bình là thứ lấy danh sách các số và giảm nó thành một số duy nhất (là mức trung bình).
chakrit

60

MapReduce là một phương pháp để xử lý song song một lượng lớn dữ liệu mà không yêu cầu nhà phát triển phải viết bất kỳ mã nào khác ngoài trình ánh xạ và giảm các hàm.

Hàm bản đồ lấy dữ liệu và đưa ra kết quả, được giữ trong một rào chắn. Hàm này có thể chạy song song với một số lượng lớn tác vụ bản đồ tương tự . Bộ dữ liệu sau đó có thể được giảm giá trị vô hướng.

Vì vậy, nếu bạn nghĩ về nó như một câu lệnh SQL

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

Chúng ta có thể sử dụng bản đồ để có được tập hợp nhân viên của mình với mức lương> 1000 mà bản đồ phát ra rào cản thành các nhóm kích thước nhóm.

Giảm sẽ tổng hợp từng nhóm. Cung cấp cho bạn bộ kết quả của bạn.

chỉ nhận được điều này từ các ghi chú nghiên cứu trường đại học của tôi trên giấy google


33
  1. Lấy một loạt dữ liệu
  2. Thực hiện một số loại chuyển đổi chuyển đổi mọi mốc thời gian sang một loại mốc khác
  3. Kết hợp những dữ liệu mới thành dữ liệu đơn giản hơn

Bước 2 là Bản đồ. Bước 3 là Giảm.

Ví dụ,

  1. Có thời gian giữa hai xung trên một cặp đồng hồ đo áp suất trên đường
  2. Ánh xạ những lần đó thành tốc độ dựa trên khoảng cách của mét
  3. Giảm các tốc độ đó xuống tốc độ trung bình

Lý do MapReduce được phân chia giữa Map và Giảm là vì các phần khác nhau có thể dễ dàng được thực hiện song song. (Đặc biệt nếu Giảm có các tính chất toán học nhất định.)

Để biết mô tả phức tạp nhưng hay về MapReduce, hãy xem: Mô hình lập trình MapReduce của Google - Xem lại (PDF) .


1
Tôi sẽ nói cho bước 3, "kết hợp" thay vì "biến đổi"
TraumaPony

Lần đầu tiên, ba câu trả lời kết hợp là câu trả lời TỐT NHẤT. Đọc liên kết bài viết đầu tiên của Nasser (cấp độ lý thuyết) Sau đó, câu trả lời của chakrit (giải thích riêng về giảm bản đồ) Bây giờ câu trả lời của Frank (Thành ngữ MapReduce nổi tiếng là gì.) Cảm ơn ba bạn. :)
Ajeet Ganga

20

MAP và REDUCE là các chức năng Lisp cũ từ thời con người giết chết những con khủng long cuối cùng.

Hãy tưởng tượng bạn có một danh sách các thành phố với thông tin về tên, số người sống ở đó và quy mô của thành phố:

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

Bây giờ bạn có thể muốn tìm thành phố có mật độ dân số cao nhất.

Đầu tiên chúng tôi tạo một danh sách tên thành phố và mật độ dân số bằng 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))

Sử dụng GIẢM GIÁ bây giờ chúng ta có thể tìm thấy thành phố có mật độ dân số lớn nhất.

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

 =>   (C 5000/7)

Kết hợp cả hai phần, chúng tôi nhận được mã sau đây:

(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*))

Hãy giới thiệu các chức năng:

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

Sau đó, chúng tôi có thể viết mã GIẢM GIÁ MAP của chúng tôi là:

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

 =>   (C 5000/7)

Nó gọi MAPREDUCE(đánh giá là từ trong ra ngoài), vì vậy nó được gọi là giảm bản đồ .


@MoMolog: hàm MAX đã tồn tại và thực hiện một số thứ hơi khác. Ngoài ra: người ta không nên xác định lại MAX.
Rainer Joswig

max-densityso sánh các yếu tố thứ hai của các đối số thông qua, phải không? Xin lỗi vì chỉnh sửa ngớ ngẩn.
Alexander Presber

@MoMolog: vâng, đó là yếu tố thứ hai và nó chỉ hữu ích trong bối cảnh của ví dụ nhỏ này. Mã này cũng được viết theo mục đích được viết bằng Lisp kiểu hơi cũ với các danh sách dưới dạng cấu trúc dữ liệu ...
Rainer Joswig

17

Hãy lấy ví dụ từ bài báo của Google . Mục tiêu của MapReduce là có thể sử dụng hiệu quả một khối lượng các đơn vị xử lý làm việc tương đương với một số loại thuật toán. Ví dụ như sau: bạn muốn trích xuất tất cả các từ và số lượng của chúng trong một bộ tài liệu.

Thực hiện điển hình:

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

Triển khai 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

Xung quanh đó, bạn sẽ có một chương trình chính sẽ phân vùng bộ tài liệu theo "phần tách" sẽ được xử lý song song cho giai đoạn Bản đồ. Các giá trị phát ra được ghi bởi công nhân trong một bộ đệm dành riêng cho công nhân. Chương trình tổng thể sau đó ủy quyền cho các công nhân khác thực hiện giai đoạn Giảm ngay khi được thông báo rằng bộ đệm đã sẵn sàng để được xử lý.

Mọi đầu ra của worker (là Map hoặc là worker worker) trên thực tế là một tệp được lưu trữ trên hệ thống tệp phân tán (GFS cho Google) hoặc trong cơ sở dữ liệu phân tán cho CouchDB.


10

Giới thiệu thực sự dễ dàng , nhanh chóng"dành cho người giả" về MapReduce có sẵn tại: http://www.marcolotz.com/?p=67

Đăng một số nội dung của nó:

Trước hết, tại sao MapReduce ban đầu được tạo ra?

Về cơ bản Google cần một giải pháp để thực hiện các công việc tính toán lớn dễ dàng song song hóa, cho phép dữ liệu được phân phối trong một số máy được kết nối qua mạng. Bên cạnh đó, nó phải xử lý lỗi máy một cách minh bạch và quản lý các vấn đề cân bằng tải.

MapReduce thế mạnh thực sự là gì?

Người ta có thể nói rằng phép thuật MapReduce dựa trên ứng dụng chức năng Map và Giảm. Tôi phải thú nhận bạn đời, rằng tôi rất không đồng ý. Tính năng chính khiến MapReduce trở nên phổ biến là khả năng song song và phân phối tự động, kết hợp với giao diện đơn giản. Các yếu tố này được tóm tắt với việc xử lý lỗi trong suốt đối với hầu hết các lỗi khiến khung này trở nên phổ biến.

Một chút sâu hơn trên giấy:

MapReduce ban đầu được đề cập trong một bài báo của Google (Dean & Ghemawat, 2004 - liên kết tại đây) như là một giải pháp để thực hiện tính toán trong Dữ liệu lớn bằng cách sử dụng cách tiếp cận song song và cụm máy tính hàng hóa. Trái ngược với Hadoop, được viết bằng Java, khung của Google được viết bằng C ++. Tài liệu mô tả cách một khung công tác song song sẽ hoạt động bằng cách sử dụng các hàm Map và Giảm từ lập trình chức năng qua các tập dữ liệu lớn.

Trong giải pháp này sẽ có hai bước chính - được gọi là Bản đồ và Thu nhỏ -, với một bước tùy chọn giữa bước đầu tiên và lần thứ hai - được gọi là Kết hợp. Bước Map sẽ chạy trước, thực hiện tính toán trong cặp giá trị khóa đầu vào và tạo ra giá trị khóa đầu ra mới. Người ta phải nhớ rằng định dạng của các cặp khóa-giá trị đầu vào không nhất thiết phải khớp với cặp định dạng đầu ra. Bước Giảm sẽ tập hợp tất cả các giá trị của cùng một khóa, thực hiện các tính toán khác trên nó. Kết quả là bước cuối cùng này sẽ xuất ra các cặp khóa-giá trị. Một trong những ứng dụng tầm thường nhất của MapReduce là triển khai đếm từ.

Mã giả cho ứng dụng này, được đưa ra dưới đây:

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

Như người ta có thể nhận thấy, bản đồ đọc tất cả các từ trong một bản ghi (trong trường hợp này bản ghi có thể là một dòng) và phát ra từ đó dưới dạng một khóa và số 1 là một giá trị. Sau đó, giảm sẽ nhóm tất cả các giá trị của cùng một khóa. Hãy cho một ví dụ: hãy tưởng tượng rằng từ 'ngôi nhà' xuất hiện ba lần trong hồ sơ. Đầu vào của bộ giảm tốc sẽ là [house, [1,1,1]]. Trong bộ giảm tốc, nó sẽ tổng hợp tất cả các giá trị cho nhà khóa và cung cấp dưới dạng đầu ra giá trị khóa sau: [house, [3]].

Đây là hình ảnh về diện mạo của nó trong khung MapReduce:

Hình ảnh từ tài liệu gốc MapReduce Google

Như một vài ví dụ cổ điển khác về các ứng dụng MapReduce, người ta có thể nói:

• Đếm tần suất truy cập URL

• Đồ thị liên kết ngược

• Grep phân phối

• Vector hạn trên mỗi máy chủ

Để tránh lưu lượng truy cập mạng quá nhiều, bài viết mô tả cách khung nên cố gắng duy trì địa phương dữ liệu. Điều này có nghĩa là nó phải luôn cố gắng đảm bảo rằng một máy đang chạy các công việc Map có dữ liệu trong bộ nhớ / bộ nhớ cục bộ của nó, tránh để lấy nó từ mạng. Nhằm mục đích giảm mạng thông qua việc đặt một trình ánh xạ, bước kết hợp tùy chọn, được mô tả trước đây, được sử dụng. Bộ kết hợp thực hiện các tính toán trên đầu ra của các bộ ánh xạ trong một máy nhất định trước khi gửi nó tới Bộ giảm tốc - có thể ở trong một máy khác.

Tài liệu cũng mô tả cách các yếu tố của khung nên hoạt động trong trường hợp có lỗi. Những yếu tố này, trong bài báo, được gọi là worker và master. Chúng sẽ được chia thành các yếu tố cụ thể hơn trong các triển khai nguồn mở. Vì Google chỉ mô tả cách tiếp cận trong bài báo và không phát hành phần mềm độc quyền của mình, nhiều khung công tác nguồn mở đã được tạo để triển khai mô hình. Như các ví dụ người ta có thể nói Hadoop hoặc tính năng MapReduce giới hạn trong MongoDB.

Thời gian chạy cần quan tâm đến các chi tiết lập trình viên không phải là chuyên gia, như phân vùng dữ liệu đầu vào, lên lịch thực hiện chương trình trên toàn bộ máy lớn, xử lý các lỗi máy (dĩ nhiên là một cách minh bạch) và quản lý giao tiếp giữa các máy . Người dùng có kinh nghiệm có thể điều chỉnh các tham số này, như cách dữ liệu đầu vào sẽ được phân vùng giữa các công nhân.

Ý chính:

Dung sai lỗi:Nó phải chịu đựng sự cố máy một cách duyên dáng. Để thực hiện điều này, chủ nhân ping định kỳ các công nhân. Nếu chủ không nhận được phản hồi từ một công nhân nhất định trong một khoảng thời gian xác định, chủ sẽ xác định công việc là thất bại ở công nhân đó. Trong trường hợp này, tất cả các nhiệm vụ bản đồ được hoàn thành bởi công nhân bị lỗi sẽ bị ném đi và được giao cho một công nhân có sẵn khác. Điều tương tự xảy ra nếu công nhân vẫn đang xử lý bản đồ hoặc tác vụ giảm. Lưu ý rằng nếu công nhân đã hoàn thành phần rút gọn của nó, tất cả các tính toán đã hoàn thành vào thời điểm nó không thành công và không cần phải thiết lập lại. Là một điểm chính của thất bại, nếu chủ thất bại, tất cả các công việc đều thất bại. Vì lý do này, người ta có thể xác định các điểm kiểm tra định kỳ cho chủ, để lưu cấu trúc dữ liệu của nó.

Địa phương: Để tránh lưu lượng mạng, khung cố gắng đảm bảo rằng tất cả dữ liệu đầu vào có sẵn cục bộ cho các máy sẽ thực hiện tính toán trên chúng. Trong mô tả ban đầu, nó sử dụng Hệ thống tệp của Google (GFS) với hệ số sao chép được đặt thành 3 và kích thước khối là 64 MB. Điều này có nghĩa là cùng một khối 64 MB (tạo một tệp trong hệ thống tệp) sẽ có các bản sao giống hệt nhau trong ba máy khác nhau. Bậc thầy biết các khối ở đâu và cố gắng sắp xếp các công việc bản đồ trong máy đó. Nếu thất bại, chủ sẽ cố gắng phân bổ một máy gần một bản sao của dữ liệu đầu vào nhiệm vụ (tức là một máy công nhân trong cùng một giá của máy dữ liệu).

• Độ chi tiết của nhiệm vụ: Giả sử rằng mỗi pha bản đồ được chia thành các mảnh M và mỗi pha Giảm được chia thành các mảnh R, lý tưởng sẽ là M và R lớn hơn rất nhiều so với số lượng máy công nhân. Điều này là do thực tế là một công nhân thực hiện nhiều nhiệm vụ khác nhau cải thiện cân bằng tải động. Bên cạnh đó, nó làm tăng tốc độ phục hồi trong trường hợp công nhân thất bại (vì nhiều tác vụ bản đồ mà nó đã hoàn thành có thể được trải ra trên tất cả các máy khác).

Nhiệm vụ sao lưu: Đôi khi, một nhân viên Map hoặc Reducer có thể cư xử chậm hơn rất nhiều so với những người khác trong cụm. Điều này có thể giữ tổng thời gian xử lý và làm cho nó bằng với thời gian xử lý của máy chậm đơn lẻ đó. Bài viết gốc mô tả một giải pháp thay thế gọi là Nhiệm vụ sao lưu, được chủ nhân lên lịch khi hoạt động MapReduce gần hoàn thành. Đây là những nhiệm vụ được lên kế hoạch bởi Master của các nhiệm vụ đang thực hiện. Do đó, hoạt động MapReduce hoàn thành khi bản chính hoặc bản sao lưu kết thúc.

Bộ đếm: Đôi khi người ta có thể muốn đếm các sự kiện xảy ra. Vì lý do này, tính nơi tạo ra. Các giá trị truy cập trong mỗi công nhân được định kỳ truyền đến chủ. Sau đó, tổng thể tổng hợp (Yep. Có vẻ như bộ tổng hợp Pregel đến từ nơi này) các giá trị truy cập của bản đồ thành công và giảm tác vụ và trả chúng về mã người dùng khi hoạt động MapReduce hoàn tất. Ngoài ra còn có một giá trị truy cập hiện tại có sẵn trong trạng thái chính, vì vậy một người theo dõi quá trình có thể theo dõi cách nó hoạt động.

Chà, tôi đoán với tất cả các khái niệm trên, Hadoop sẽ là một miếng bánh cho bạn. Nếu bạn có bất kỳ câu hỏi nào về bài viết MapReduce ban đầu hoặc bất cứ điều gì liên quan, xin vui lòng cho tôi biết.


4

Tôi không muốn nghe có vẻ nghiêm túc, nhưng điều này đã giúp tôi rất nhiều, và nó khá đơn giản:

cat input | map | reduce > output

4

Nếu bạn đã quen thuộc với Python, sau đây là lời giải thích đơn giản nhất có thể về 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

Xem cách từng phân đoạn dữ liệu thô được xử lý riêng lẻ, trong trường hợp này, nhân với 2 (phần bản đồ của MapReduce). Dựa trên mapped_result, chúng tôi đã kết luận rằng kết quả sẽ là 42(phần giảm của MapReduce).

Một kết luận quan trọng từ ví dụ này là thực tế là mỗi đoạn xử lý không phụ thuộc vào đoạn khác. Ví dụ, nếu thread_1bản đồ [1, 2, 3]thread_2bản đồ [4, 5, 6], kết quả cuối cùng của cả hai luồng vẫn sẽ [2, 4, 6, 8, 10, 12]nhưng chúng tôi đã giảm một nửa thời gian xử lý cho việc này. Điều tương tự cũng có thể nói đối với hoạt động giảm và là bản chất của cách MapReduce hoạt động trong tính toán song song.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.