题
我听说过很多关于 Map/Reduce 的内容,尤其是在 Google 大规模并行计算系统的背景下。到底是什么?
解决方案
这是谷歌的抽象的MapReduce 研究出版物页面:
的MapReduce是一个编程模型和 一个相关的实施 处理,并产生较大的数据 集。用户可以指定一个地图功能 其处理一个键/值对来 生成一组中间 键/值对,以及减少功能 该合并所有中间值 与相同的中间相关联 键。
的MapReduce的优点是,可以并行地对多个处理节点(多个服务器)来执行该处理,以便其是可以很好地进行缩放的系统。
,因为它是从功能编程模型中,基于map
并且每个不reduce
步骤有(从map
过程不依赖于另一个的每个子区段的状态和结果)的任何副作用,因此数据集被映射的,并且减少了可以各自被分离在多个处理节点。
乔尔的你的编程语言可以这样做?一块讨论如何理解函数式编程是谷歌必须想出MapReduce的,哪些权力的搜索引擎。这是一个非常良好的阅读,如果你不熟悉函数式编程,以及如何允许可伸缩的代码。
相关问题:请解释MapReduce的简单
其他提示
据介绍比我能更好。帮助?
地图是适用其他功能列表上的所有项目,生产出与它的所有的返回值的另一个列表的功能。 (称“申请F到X”的另一种方法是“调用F,并向它传递×”。所以有时它听起来更好说“应用”,而不是“呼叫”。)
这是地图是如何可能在C#编写(它被称为Select
并且是在标准库):
public static IEnumerable<R> Select<T, R>(this IEnumerable<T> list, Func<T, R> func)
{
foreach (T item in list)
yield return func(item);
}
由于你是一个Java的家伙,和Joel Spolsky的喜欢讲述如何糟糕Java是极不公平的谎言(实际上,他没有说谎,这是糟糕的,但我想拉拢你),这是我非常在Java版本粗糙的尝试(我没有Java编译器,我依稀记得Java版本1.1!):
// represents a function that takes one arg and returns a result
public interface IFunctor
{
object invoke(object arg);
}
public static object[] map(object[] list, IFunctor func)
{
object[] returnValues = new object[list.length];
for (int n = 0; n < list.length; n++)
returnValues[n] = func.invoke(list[n]);
return returnValues;
}
我敢肯定,这可以在一万元的方式来改善。但它的基本思想。
减少是把一个列表中的所有项组合成一个值的函数。要做到这一点,它需要得到另一个功能func
,轮流两个项目为一个值。这将给予前两个项目func
工作。那么,随着第三个项目一起的结果。那么,随着第四个项目,依此类推结果直到所有的项目都走了,我们只剩下一个值。
在C#减少被称为Aggregate
并再次是在标准库。我会直接跳到一个Java版本:
// represents a function that takes two args and returns a result
public interface IBinaryFunctor
{
object invoke(object arg1, object arg2);
}
public static object reduce(object[] list, IBinaryFunctor func)
{
if (list.length == 0)
return null; // or throw something?
if (list.length == 1)
return list[0]; // just return the only item
object returnValue = func.invoke(list[0], list[1]);
for (int n = 1; n < list.length; n++)
returnValue = func.invoke(returnValue, list[n]);
return returnValue;
}
这些Java版本需要仿制药加入到他们,但我不知道该怎么做,在爪哇。但是,你应该能够通过他们的匿名内部类提供的仿函数:
string[] names = getLotsOfNames();
string commaSeparatedNames = (string)reduce(names,
new IBinaryFunctor {
public object invoke(object arg1, object arg2)
{ return ((string)arg1) + ", " + ((string)arg2); }
}
希望仿制药就会改掉了铸件。类型安全等效于C#是:
string commaSeparatedNames = names.Aggregate((a, b) => a + ", " + b);
这是为什么“酷”?分手较大计算成小块,使他们能够以不同的方式一起放回简单的方法,总是很酷。谷歌应用这种想法的方式是并行的,因为这两个地图和降低可以在多台计算机共享出来。
但关键的要求是不是你的语言可以把函数作为值。任何面向对象的语言能做到这一点。并行化的实际要求是,你通过小func
功能映射和减少不得使用或更新任何状态。他们必须返回一个值,该值仅依赖于传递给它们的参数(S)。否则,结果将完全搞砸了,当你尝试运行整个事情并行。
在对很长的华夫饼或很短的模糊博客文章感到非常沮丧之后,我最终发现了这一点 非常好的严谨简洁的论文.
然后我继续通过翻译成 Scala 使其更加简洁,其中我提供了最简单的情况,用户只需指定 map
和 reduce
应用程序的一部分。严格来说,在 Hadoop/Spark 中,采用了更复杂的编程模型,要求用户显式指定此处概述的另外 4 个函数: http://en.wikipedia.org/wiki/MapReduce#Dataflow
import 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
}
地图是一个本地JS方法可应用于阵列。它创建了一个新的数组作为原始阵列中映射到每个元素的一些功能的结果。所以,如果你映射函数(元素){回报元素* 2;},它会返回与每一个元素的新数组一倍。原始数组会去未修饰的。
HTTPS://developer.mozilla .ORG / EN-US /文档/网络/ JavaScript的/参考/ Global_Objects /阵列/地图
减少是一个本地JS方法,该方法也可应用于阵列。它应用一个函数的阵列,并且具有称为蓄能器的初始输出值。它循环通过每个元件的阵列中,应用一个函数,并将其降低到一个值(始于作为累加器)。它是有用的,因为你可以有你想要的任何输出,你就必须开始与式蓄能器。所以,如果我想减少一些成一个对象,我将开始与蓄能器{}
HTTPS:/ /developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce?v=a
的MapReduce:
要运行一些大的,我们可以用不同的计算机的计算能力在我们的办公室。困难的部分是不同的分裂间computers.It任务由MapReduce的库来完成。
其基本思想是,你把工作分成了两个部分:一个Map和减少。地图基本上采用的问题,将其分解成子部分,并将子部分不同的机器 - 所以所有的作品在同一时间运行。减少需要从子部分的结果,并将其组合到一起以获得一个答案。
输入是地图计算records.Result的列表被键/值对的列表。减少取各组值具有相同的密钥,然后将它们合并成一个单一的value.You说不出的作业是否被分成100件或2件;最终的结果看起来很像单个地图的结果。
请着眼于简单的地图,并减少程序:
地图功能是用来申请我们原来名单上的一些功能,并由此产生一个新的列表。在Python地图()函数中的函数和一个列表作为参数。一个新的列表是通过将函数列表的每个项返回。
li = [5, 7, 4, 9]
final_list = list(map(lambda x: x*x , li))
print(final_list) #[25, 49, 16, 81]
Python中的减少()函数中的函数和一个列表作为参数。该函数调用lambda函数和列表,并返回一个新的降低的结果。这将执行比对的列表中的重复操作。
#reduce func to find product/sum of list
x=(1,2,3,4)
from functools import reduce
reduce(lambda a,b:a*b ,x) #24