分布式系统MIT 6.824 lab1-part3

Part III: Distributing MapReduce tasks

任务描述

完成单机分布式的MapReduce任务。

完成mapreduce/schedule.go中的schedule()函数。

schedule()函数的功能是将任务交付给可用的worker()。

涉及到的代码

  1. mapreduce/master.go
  2. mapreduce/common_rpc.go
  3. mapreduce/worker.go

Hint

  • rpc doc 需要翻墙

  • go test -race -run TestParallel > out.测试有没有竞争条件。

  • go test -run TestParallel

  • sync.WaitGroup

Sequential的schedule调度函数

func(phase jobPhase) {
		switch phase {
		case mapPhase:
			for i, f := range mr.files {
				doMap(mr.jobName, i, f, mr.nReduce, mapF)
			}
		case reducePhase:
			for i := 0; i < mr.nReduce; i++ {
				doReduce(mr.jobName, i, mergeName(mr.jobName, i), len(mr.files), reduceF)
			}
		}
	}

设计思路

使用一个变量currentTask来记录当前需要被分配的任务id,当currentTask==ntasks时,代表任务已经分配完成。

主goroutine的任务是,使用非阻塞IO不断地读registerChan里的内容,每侦听到一个就建立一个新的goroutine来做RPC调用。

原子锁的使用

var ops uint64 = 0
atomic.AddUint64(&ops, 1)
atomic.LoadUint64(&ops)

使用原子锁来记录当前的任务编号。

代码

func schedule(jobName string, mapFiles []string, nReduce int, phase jobPhase, registerChan chan string) {
	var ntasks int
	var n_other int // number of inputs (for reduce) or outputs (for map)
	switch phase {
	case mapPhase:
		ntasks = len(mapFiles)
		n_other = nReduce
	case reducePhase:
		ntasks = nReduce
		n_other = len(mapFiles)
	}

	fmt.Printf("Schedule: %v %v tasks (%d I/Os)\n", ntasks, phase, n_other)

	// All ntasks tasks have to be scheduled on workers. Once all tasks
	// have completed successfully, schedule() should return.
	//
	// Your code here (Part III, Part IV).
	//
	var currentTask int32= 0
	var mutexForTask = &sync.Mutex{}
	var wg sync.WaitGroup
	for atomic.LoadInt32(&currentTask)<int32(ntasks){
		select{
		case workerName := <-registerChan:
			wg.Add(1)
			go func(routeWorker string) {
				for{
					mutexForTask.Lock()
					currentId := atomic.LoadInt32(&currentTask)
					if currentId<int32(ntasks){
						atomic.AddInt32(&currentTask,1)
						mutexForTask.Unlock()
						//start do work
						args:= new(DoTaskArgs)
						args.File = mapFiles[currentId]
						args.JobName = jobName
						args.NumOtherPhase = n_other
						args.Phase = phase
						args.TaskNumber = int(currentId)
						ok := call(routeWorker, "Worker.DoTask", args, new(struct{}))
						if ok == false {
							debug("rpc error currentId ",currentId)
						} else {
							debug("success ",currentId)
						}
					}
					if currentId >= int32(ntasks){
						wg.Add(-1)
						mutexForTask.Unlock()
						debug("work done ",currentId)
						return
					}
				}
			}(workerName)
		default:
			continue
		}
	}
	//wait for job complete
	wg.Wait()
	fmt.Printf("Schedule: %v done\n", phase)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值