⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sortedsched.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
// -*- c-basic-offset: 4 -*-/* * sortedsched.{cc,hh} -- bin-packing sort for tasks (SMP Click) * Benjie Chen, Eddie Kohler * * Copyright (c) 1999-2000 Massachusetts Institute of Technology * Copyright (c) 2004 Regents of the University of California * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/standard/scheduleinfo.hh>#include "sortedsched.hh"#include <click/task.hh>#include <click/routerthread.hh>#include <click/router.hh>#include <click/master.hh>#include <click/glue.hh>#include <click/confparse.hh>#include <click/task.hh>#include <click/error.hh>#define DEBUG 0#define KEEP_GOOD_ASSIGNMENT 1BalancedThreadSched::BalancedThreadSched()    : _timer(this){}BalancedThreadSched::~BalancedThreadSched(){}  int BalancedThreadSched::configure(Vector<String> &conf, ErrorHandler *errh){    _interval = 1000;    _increasing = true;    if (cp_va_parse(conf, this, errh, 		    cpOptional,		    cpUnsigned, "interval", &_interval, 		    cpBool, "increasing?", &_increasing, cpEnd) < 0)	return -1;    return 0;}intBalancedThreadSched::initialize(ErrorHandler *){    _timer.initialize(this);    _timer.schedule_after_ms(10);    return 0;}static int task_increasing_sorter(const void *va, const void *vb) {    Task **a = (Task **)va, **b = (Task **)vb;    return (*a)->cycles() - (*b)->cycles();}static int task_decreasing_sorter(const void *va, const void *vb) {    Task **a = (Task **)va, **b = (Task **)vb;    return (*b)->cycles() - (*a)->cycles();}voidBalancedThreadSched::run_timer(){    Master *m = router()->master();    // develop load list    Vector<int> load;    int total_load = 0;    for (int tid = 0; tid < m->nthreads(); tid++) {	RouterThread *thread = m->thread(tid);	thread->lock_tasks();	int thread_load = 0;	for (Task *t = thread->scheduled_next(); t != thread; t = t->scheduled_next())	    thread_load += t->cycles();	thread->unlock_tasks();	total_load += thread_load;	load.push_back(thread_load);    }    int avg_load = total_load / m->nthreads();    for (int rounds = 0; rounds < m->nthreads(); rounds++) {	// find min and max loaded threads	int min_tid = 0, max_tid = 0;	for (int tid = 1; tid < m->nthreads(); tid++)	    if (load[tid] < load[min_tid])		min_tid = tid;	    else if (load[tid] > load[max_tid])		max_tid = tid;#if KEEP_GOOD_ASSIGNMENT	// do nothing if load difference is minor	if ((avg_load - load[min_tid] < (avg_load >> 3))	    && (load[max_tid] - avg_load < (avg_load >> 3)))	    break;#endif	// lock max_thread	RouterThread *thread = m->thread(max_tid);	thread->lock_tasks();		// collect tasks from max-loaded thread	total_load -= load[max_tid];	load[max_tid] = 0;	Vector<Task *> tasks;	for (Task *t = thread->scheduled_next(); t != thread; t = t->scheduled_next()) {	    load[max_tid] += t->cycles();	    tasks.push_back(t);	}	total_load += load[max_tid];	avg_load = total_load / m->nthreads();		// sort tasks by cycle count	click_qsort(tasks.begin(), tasks.size(), sizeof(Task *), (_increasing ? task_increasing_sorter : task_decreasing_sorter));	// move tasks	int highwater = avg_load + (avg_load >> 2);	for (Task **tt = tasks.begin(); tt < tasks.end(); tt++)	    if (load[min_tid] + (*tt)->cycles() < highwater		&& load[min_tid] + 2*(*tt)->cycles() <= load[max_tid]) {		load[min_tid] += (*tt)->cycles();		load[max_tid] -= (*tt)->cycles();		(*tt)->change_thread(min_tid);	    }	// done with this round!	thread->unlock_tasks();    }      _timer.schedule_after_ms(_interval);}#if 0voidBalancedThreadSched::run_timer(){    Vector<Task*> tasks;    unsigned total_load = 0;    unsigned avg_load;    int n = router()->nthreads();    int load[n];      for(int i=0; i<n; i++) load[i] = 0;    TaskList *task_list = router()->task_list();    task_list->lock();    Task *t = task_list->all_tasks_next();    while (t != task_list) {	total_load += t->cycles();	if (t->thread_preference() >= 0) 	    load[t->thread_preference()] += t->cycles();	tasks.push_back(t);	t = t->all_tasks_next();    }    task_list->unlock();    avg_load = total_load / n;#if KEEP_GOOD_ASSIGNMENT    int ii;    for(ii=0; ii<n; ii++) {	unsigned diff = avg_load>load[ii] ? avg_load-load[ii] : load[ii]-avg_load;	if (diff > (avg_load>>3)) {#if DEBUG > 1	    click_chatter("load balance, avg %u, diff %u", avg_load, diff);#endif	    break;	}    }    if (ii == n) {	_timer.schedule_after_ms(_interval);	return;    }#endif  #if DEBUG > 1    int print = 0;    int high = 0;#endif    // slow sorting algorithm, but works okay for small number of tasks    Vector<Task*> sorted;    for (int i=0; i<tasks.size(); i++) {	int max = 0;	int which = -1;	for (int j=0; j<tasks.size(); j++) {	    if (tasks[j] && tasks[j]->cycles() > max) { 		which = j; 		max = tasks[j]->cycles();	    }	}	assert(which >= 0);	sorted.push_back(tasks[which]);	tasks[which] = 0;#if DEBUG > 1	if (i == 0) high = max;#endif    }#if DEBUG > 1    if (high >= 500) {	print = 1;	unsigned now = click_jiffies();	for(int i=0; i<sorted.size(); i++) {	    Element *e = sorted[i]->element();	    if (e)		click_chatter("%u: %s %d, was on %d", 			      now, e->id().cc(), 			      sorted[i]->cycles(), 			      sorted[i]->thread_preference());	}    }#endif    Vector<Task*> schedule[n];    for(int i=0; i<n; i++) load[i] = 0;    int min, which;    int i = _increasing ? sorted.size()-1 : 0;    while (1) {	min = load[0];	which = 0;	for (int j = 1; j < n; j++) {	    if (load[j] < min) {		which = j;		min = load[j];	    }	}	load[which] += sorted[i]->cycles();	schedule[which].push_back(sorted[i]);	sorted[i]->change_thread(which);	if (_increasing) {	    if (i == 0) break;	    else i--;	} else {	    if (i == sorted.size()-1) break;	    else i++;	}    }  #if DEBUG > 1    if (print) {	unsigned now = click_jiffies();	for(int i=0; i<sorted.size(); i++) {	    Element *e = sorted[i]->element();	    if (e) 		click_chatter("%u: %s %d, now on %d (%d)", 			      now, e->id().cc(), 			      sorted[i]->cycles(), 			      sorted[i]->thread_preference(), avg_load);	}	print = 0;	click_chatter("\n");    }#endif    _timer.schedule_after_ms(_interval);}#endifELEMENT_REQUIRES(linuxmodule smpclick)EXPORT_ELEMENT(BalancedThreadSched BalancedThreadSched-SortedTaskSched)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -