MIT6.824-Lab1-Part II: Single-worker word count

508 阅读2分钟

1.概述

在main/wc.go中有空的mapF()和reduceF()函数,Part II的内容就是实现这两个函数,以统计每个单词出现的次数,区分大小写。替换掉Part I中的MapFunc和ReduceFunc。
在~/6.824/src/main中有一些名称类似pg-*.txt的文件,这便是Part II要处理的输入文件,运行下列命令来测试程序

cd 6.824
export "GOPATH=$PWD"
cd "$GOPATH/src/main"
go run wc.go master sequential pg-*.txt

最终的输出文件是mrtmp.wcseq,若程序编写正确,最终读取mrtmp.wcseq可以得到如下结果

sort -n -k2 mrtmp.wcseq | tail -10
that: 7871
it: 7987
in: 8415
was: 8578
a: 13382
of: 13536
I: 14296
to: 16079
and: 23612
the: 29748

2.mapF()

对每个输入文件会调用一次mapF,第一个参数是文件名,第二个参数是文件的内容,最后返回键值对切片。

func mapF(filename string, contents string) []mapreduce.KeyValue {
    // Your code here (Part II).
}

返回的键值对切片中,Kay存放的是单词,Value存放的是这个单词在这篇文章中出现的次数。使用strings.Fields方法对输入文件的内容进行分割.还有需要注意的一点是,需要将标点符号进行替换,以免在按间隔符分割得到单词后,由于存在标点符号问题不能匹配成功。实现如下(ps.比较好的方式是使用strings.FieldsFunc):

func mapF(filename string, contents string) []mapreduce.KeyValue {
    //删除,.?等等标点符号
    re, _ := regexp.Compile("[^a-z^A-Z]")
    contents = re.ReplaceAllString(contents, " ")

    var kv map[string]int
    kv = make(map[string]int)
    words := strings.Fields(contents)
    for _, w := range words {
        if _,ok := kv[w];ok {//word已经存在,计数累加
            kv[w] +=1
        }else {
                kv[w] =1
        }
    }
    //转换为[]mapreduce.KeyValue
    var res []mapreduce.KeyValue
    for k,v := range kv {
        res = append(res,mapreduce.KeyValue{k,strconv.Itoa(v)})
    }

    return res
}

3.reduceF()

reduceF()对map tasks产生的每一个key都调用一次,values存放的是key在不同输入文件中出现的次数.在reduceF将values都相加然后返回就是每个单词在所有文件中出现的次数。

func reduceF(key string, values []string) string {
    // Your code here (Part II).
}

实现如下

func reduceF(key string, values []string) string {
    total := 0
    for _,v := range values {
        i, err := strconv.Atoi(v)
        if err!=nil {
            fmt.Println(err)
        }
        total += i
    }
    return strconv.Itoa(total)
}

4.测试运行

cd "$GOPATH/src/main"
time go run wc.go master sequential pg-*.txt

出现类似下面结果运行成功

查看生成的结果文件mrtmp.wcseq,能与下面内容一致则说明程序运行正确

sort -n -k2 mrtmp.wcseq | tail -10
that: 7871
it: 7987
in: 8415
was: 8578
a: 13382
of: 13536
I: 14296
to: 16079
and: 23612
the: 29748

或者直接运行这个脚本测试

bash ./test-wc.sh