J'entends beaucoup parler de carte / réduction, en particulier dans le contexte du système de calcul massivement parallèle de Google. Qu'est-ce que c'est exactement?
language-agnostic
mapreduce
Lawrence Dol
la source
la source
Réponses:
Extrait du résumé de la page de publication de recherche MapReduce de Google :
L'avantage de MapReduce est que le traitement peut être effectué en parallèle sur plusieurs nœuds de traitement (plusieurs serveurs), c'est donc un système qui peut très bien évoluer.
Étant donné qu'il est basé à partir de la programmation fonctionnelle modèle, la
map
et lesreduce
étapes chaque ne pas avoir d'effets secondaires (l'état et les résultats de chaque sous - section d'unmap
processus ne dépend pas de l' autre), de sorte que l'ensemble de données étant mis en correspondance et réduit peuvent chacun être séparés sur plusieurs nœuds de traitement.Joel's Votre langage de programmation peut-il faire cela? L'article explique comment la compréhension de la programmation fonctionnelle était essentielle dans Google pour créer MapReduce, qui alimente son moteur de recherche. C'est une très bonne lecture si vous n'êtes pas familier avec la programmation fonctionnelle et comment elle permet un code évolutif.
Voir aussi: Wikipedia: MapReduce
Question connexe: veuillez expliquer mapreduce simplement
la source
MapReduce expliqué .
Cela explique mieux que ce que je peux. Aide-t-il?
la source
Map est une fonction qui applique une autre fonction à tous les éléments d'une liste, pour produire une autre liste avec toutes les valeurs de retour dessus. (Une autre façon de dire "appliquer f à x" est "appeler f, en lui passant x". Donc, parfois, il semble plus agréable de dire "appliquer" au lieu de "appeler".)
Voici comment la carte est probablement écrite en C # (elle est appelée
Select
et se trouve dans la bibliothèque standard):Comme vous êtes un mec Java, et que Joel Spolsky aime dire à DES MENSONGES GROSSEMENT INJUSTE à quel point Java est merdique (en fait, il ne ment pas, c'est merdique, mais j'essaie de vous convaincre), voici ma tentative très difficile de une version Java (je n'ai pas de compilateur Java, et je me souviens vaguement de la version 1.1 de Java!):
Je suis sûr que cela peut être amélioré de mille façons. Mais c'est l'idée de base.
Réduire est une fonction qui transforme tous les éléments d'une liste en une seule valeur. Pour ce faire, il doit être doté d'une autre fonction
func
qui transforme deux éléments en une seule valeur. Cela fonctionnerait en donnant les deux premiers éléments àfunc
. Puis le résultat de cela avec le troisième élément. Ensuite, le résultat de cela avec le quatrième élément, et ainsi de suite jusqu'à ce que tous les éléments aient disparu et qu'il nous reste une valeur.En C #, la réduction est appelée
Aggregate
et est à nouveau dans la bibliothèque standard. Je vais passer directement à une version Java:Ces versions de Java ont besoin d'être ajoutées à des génériques, mais je ne sais pas comment faire cela en Java. Mais vous devriez pouvoir leur passer des classes internes anonymes pour fournir les foncteurs:
Espérons que les génériques élimineraient les moulages. L'équivalent typeafe en C # est:
Pourquoi est-ce «cool»? Les moyens simples de diviser des calculs plus volumineux en petits morceaux, afin qu'ils puissent être reconstitués de différentes manières, sont toujours intéressants. Google applique cette idée à la parallélisation, car la carte et la réduction peuvent être partagées sur plusieurs ordinateurs.
Mais l'exigence clé n'est PAS que votre langage puisse traiter les fonctions comme des valeurs. N'importe quel langage OO peut le faire. L'exigence réelle pour la parallélisation est que les petites
func
fonctions que vous passez à mapper et à réduire ne doivent utiliser ou mettre à jour aucun état. Ils doivent renvoyer une valeur qui dépend uniquement du ou des arguments qui leur sont passés. Sinon, les résultats seront complètement foirés lorsque vous essayez d'exécuter le tout en parallèle.la source
Après avoir été très frustré par les très longs waffley ou les très courts articles de blog vagues, j'ai finalement découvert ce très bon article concis et rigoureux .
Ensuite, je suis allé de l'avant et je l'ai rendu plus concis en traduisant en Scala, où j'ai fourni le cas le plus simple où un utilisateur spécifie simplement les parties
map
etreduce
de l'application. Dans Hadoop / Spark, à proprement parler, un modèle de programmation plus complexe est utilisé qui oblige l'utilisateur à spécifier explicitement 4 autres fonctions décrites ici: http://en.wikipedia.org/wiki/MapReduce#Dataflowimport scalaz.syntax.id._ trait MapReduceModel { type MultiSet[T] = Iterable[T] // `map` must be a pure function def mapPhase[K1, K2, V1, V2](map: ((K1, V1)) => MultiSet[(K2, V2)]) (data: MultiSet[(K1, V1)]): MultiSet[(K2, V2)] = data.flatMap(map) def shufflePhase[K2, V2](mappedData: MultiSet[(K2, V2)]): Map[K2, MultiSet[V2]] = mappedData.groupBy(_._1).mapValues(_.map(_._2)) // `reduce` must be a monoid def reducePhase[K2, V2, V3](reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)]) (shuffledData: Map[K2, MultiSet[V2]]): MultiSet[V3] = shuffledData.flatMap(reduce).map(_._2) def mapReduce[K1, K2, V1, V2, V3](data: MultiSet[(K1, V1)]) (map: ((K1, V1)) => MultiSet[(K2, V2)]) (reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)]): MultiSet[V3] = mapPhase(map)(data) |> shufflePhase |> reducePhase(reduce) } // Kinda how MapReduce works in Hadoop and Spark except `.par` would ensure 1 element gets a process/thread on a cluster // Furthermore, the splitting here won't enforce any kind of balance and is quite unnecessary anyway as one would expect // it to already be splitted on HDFS - i.e. the filename would constitute K1 // The shuffle phase will also be parallelized, and use the same partition as the map phase. abstract class ParMapReduce(mapParNum: Int, reduceParNum: Int) extends MapReduceModel { def split[T](splitNum: Int)(data: MultiSet[T]): Set[MultiSet[T]] override def mapPhase[K1, K2, V1, V2](map: ((K1, V1)) => MultiSet[(K2, V2)]) (data: MultiSet[(K1, V1)]): MultiSet[(K2, V2)] = { val groupedByKey = data.groupBy(_._1).map(_._2) groupedByKey.flatMap(split(mapParNum / groupedByKey.size + 1)) .par.flatMap(_.map(map)).flatten.toList } override def reducePhase[K2, V2, V3](reduce: ((K2, MultiSet[V2])) => MultiSet[(K2, V3)]) (shuffledData: Map[K2, MultiSet[V2]]): MultiSet[V3] = shuffledData.map(g => split(reduceParNum / shuffledData.size + 1)(g._2).map((g._1, _))) .par.flatMap(_.map(reduce)) .flatten.map(_._2).toList }
la source
MapReduce et / ou SQL:
http://www.data-miners.com/blog/2008/01/mapreduce-and-sql-aggregations.html
http://www.data-miners.com/blog/
critique de MapReduce
http://www.databasecolumn.com/2008/01/mapreduce-a-major-step-back.html
http://www.databasecolumn.com/2008/01/mapreduce-continued.html
la source
Map est une méthode JS native qui peut être appliquée à un tableau. Il crée un nouveau tableau à la suite d'une fonction mappée à chaque élément du tableau d'origine. Donc, si vous mappez une fonction (élément) {élément de retour * 2;}, il renverra un nouveau tableau avec chaque élément doublé. Le tableau d'origine ne serait pas modifié.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Réduire est une méthode JS native qui peut également être appliquée à un tableau. Il applique une fonction à un tableau et a une valeur de sortie initiale appelée accumulateur. Il parcourt chaque élément du tableau, applique une fonction et les réduit à une valeur unique (qui commence par l'accumulateur). C'est utile car vous pouvez avoir n'importe quelle sortie que vous voulez, il vous suffit de commencer avec ce type d'accumulateur. Donc si je voulais réduire quelque chose en objet, je commencerais par un accumulateur {}.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?v=a
la source
MapReduce:
Pour exécuter quelque chose de grand, nous pouvons utiliser la puissance de calcul de différents ordinateurs dans notre bureau. La partie la plus difficile est de diviser la tâche entre différents ordinateurs.Cela est fait par la bibliothèque MapReduce.
L'idée de base est de diviser le travail en deux parties: une carte et une réduction. Map prend essentiellement le problème, le divise en sous-parties et envoie les sous-parties à différentes machines - de sorte que toutes les pièces fonctionnent en même temps. Réduire prend les résultats des sous-parties et les combine pour obtenir une seule réponse.
L'entrée est une liste d'enregistrements. Le résultat du calcul de la carte est une liste de paires clé / valeur. Réduire prend chaque ensemble de valeurs qui a la même clé et les combine en une seule valeur. Vous ne pouvez pas dire si le travail a été divisé en 100 morceaux ou en 2 morceaux; le résultat final ressemble à peu près au résultat d'une seule carte.
Veuillez regarder une carte simple et réduire le programme:
La fonction de carte est utilisée pour appliquer une fonction sur notre liste d'origine et une nouvelle liste est donc générée. La fonction map () en Python prend une fonction et une liste comme argument. Une nouvelle liste est renvoyée en appliquant une fonction à chaque élément de la liste.
La fonction reduction () en Python prend une fonction et une liste comme argument. La fonction est appelée avec une fonction lambda et une liste et un nouveau résultat réduit est renvoyé. Ceci effectue une opération répétitive sur les paires de la liste.
la source