目录:
细分目录:
总体而言没什么难度。
- Master 进程负责管理各个任务的状态、分配任务
- Worker 执行后,根据哈希保存到相应路径,再向 Master 发送消息
- “我做完了”,“你可以更新下这个任务的状态了”
- “我想要一个新任务”,“你可以在 response 里给我回复一个新任务”
注意 Master 是一个服务, Worker 主动向 Master 发生请求。
用 socket + go rpc 协议交互。
大概读了下论文,最大的区别在于:
- 论文中 Master 还记录了需要 Reduce 文件 list ,但是我是基于文件命名规则在 Worker 中 glob 的
go build $RACE -buildmode=plugin wc.go
# load
../mrsequential ../../mrapps/wc.soIn mrsequential codes:
mapf, reducef := loadPlugin(os.Args[1])这点论文 4.5 和作业提示中都提到了。
似乎 linux 中拷贝这个过程是具备原子性的。
或者说可以套用 groupby 框架?
比如论文中的 2.3 More Examples 章节,提到的事例,都是 groupby 。
map (k1, v1) -> list(k2, v2)
reduce (k2, list(v2)) -> list(v2)
比如 wc.go
func Map(filename string, contents string) []mr.KeyValue {
// function to detect word separators.
ff := func(r rune) bool { return !unicode.IsLetter(r) }
// split contents into an array of words.
words := strings.FieldsFunc(contents, ff)
kva := []mr.KeyValue{}
for _, w := range words {
kv := mr.KeyValue{w, "1"}
kva = append(kva, kv)
}
return kva
}
//
// The reduce function is called once for each key generated by the
// map tasks, with a list of all the values created for that key by
// any map task.
//
func Reduce(key string, values []string) string {
// return the number of occurrences of this word.
return strconv.Itoa(len(values))
}值得注意的是,把相同 key 对应的 values 这一行为“聚合”起来这一行为,并不由 reduce 来处理,而是在 reduce 前, sort by key ,然后得到各个 key 的 list of value 。
我是否能将其转换为 groupby 呢?我尝试下:
from typing import List, Tuple
import pandas as pd
from itertools import groupby, chain
# 这里之所以留着 filename ,大概是为了保留全量 input 信息,比如 indexer 时构建 values 时会用到
def Map(filename: str, contents: str) -> List[Tuple[str, str]]:
lis = contents.split(' ')
return [(x, '1') for x in lis]
def Reduce(key: str, values: List[str]) -> str:
return sum([int(x) for x in values])
meta_data = [
{'filename': 'whale', 'contents': 'a lot of words'},
{'filename': 'horse', 'contents': 'a little speak'},
]
# map
intermediate = map(lambda x: Map(x['filename'], x['contents']), meta_data)
# merge data for keys
# 在实操中,并不会把所有 keys 的数据都 merge ,然后排序
# 而是也会根据 hash 把 keys 分组,然后 load ,然后排序, reduce
intermediate = chain.from_iterable(intermediate)
intermediate = list(intermediate)
for key, key_values in groupby( # 注意这里需要 sorted,
# https://docs.python.org/3/library/itertools.html
# groupby 需要 sort 才能全部合并 key
sorted(intermediate, key=lambda x: x[0]),
lambda x: x[0]):
values = [x[1] for x in key_values]
print(key, Reduce(key, values))还有一篇 scala 文章: