MapReduce是并行计算中非常重要的一部分,本文为MapReduce扫盲贴,所谓的MapReduce主要分为Map和Reduce两部分内容,也就是先进行任务拆分给多个CPU进行计算然后再将计算结果进行归约…
并发与并行(Concurrency and Parallelism)
在开始之前,我们先普及一下并发和并行的概念。并发和并行是两个截然不同的概念,他们之间的区别要讲起来是比较晦涩难懂的,网上看的很多解释都使用逻辑控制流来进行解释,有的人反而越看越不明白。以下引用Rob Pike的演讲中的一小段进行解释上的这样一句话:
Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.
Concurrency is goal for structure, Parallelism is goal for execute
极端一点,简单来说就是“并发”指的是同时处理很多事情(可以是相同的或不同的事情),“并行”指的是同时做大量的工作(强调的是量,通常情况下是做相同的工作,当然从某种情况下来讲也可以是不相同的)。
MapReduce思想
MapReduce核心思想就是将一个任务分成多份,并行的去执行,执行完成后再把所有结果统一起来。所以它分为两个主要过程
- 任务拆分,就是Map过程
- 结果整合,就是Reduce过程
使用golang的goroutine进行模拟
MapReduce的目的就是为了让计算变得更快,我们这里使用经典的求和任务来进行模拟
- 任务:计算 1 + 2 + 3 + … + 100000 的结果
传统的实现方法–一次循环搞定(以下代码都使用golang语法演示)
1
2
3
4
5
6
7func add1(start, end int) int {
sum := 0
for i := start; i <= end; i++ {
sum += i
}
return sum
}哈哈哈,当然还有更聪明的办法
1
2
3func add2(start, end int) int{
return (end - start + 1) * (end + start) / 2
}前面介绍的两种方法,写过代码的都知道,下面使用goroutine与channel进行模拟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28func add3(start, end int) int{
rout_num := 4 // 定义使用4个goroutine进行计算
ch := make(chan int) // 定义一个channel用来传递每个goroutine计算结束后的结果
// Map操作,将计算任务分配下去
// 第一个goroutine计算 1 + 5 + 9 + ...
// 第二个goroutine计算 2 + 6 + 10 + ...
// ...
for i := 0; i < rout_num; i++ {
go func(start, end, step int) {
sum := 0
for i := start; i <= end; i += step {
sum += i
}
ch <- sum // goroutine计算完成后将结果送给channel等待主程序接收
}(start + i, end, rout_num)
}
// Reduce操作
// 从channel中取出各个goutine计算的结果
// 并将各个goroutine的计算结果加和得到最终结果
sum := 0
for i := 0; i < rout_num; i++ {
sum += <-ch
}
return sum
}
最后说明
虽然使用goroutine进行模拟,但golang中goroutine的设计初衷还是用来实现更高的并发,本文重点还请放在MapReduce思想上,因为也是菜鸟一枚,欢迎各位大牛留言交流。