Max-Min Fairness带宽分配算法

最近再写一个网络仿真器,里面参考了Max-MinFairness算法,这是一种比较理想、公平的带宽分配算法。其思路主要如下:首先是算法的准备,考察某一时刻的网络中所有的flow,由于每条flow都有其各个link,因此可以得到各个link上所有流经的flow,然后开始迭代,各个link都把capacity平均分给所有流经的flow,接着每条flow的速度就等于其最小link分配的带宽,然后每条link的剩余带宽就等于link的capacity减去所有流经的flow的速度的总和,再然后把link的剩余带宽作为capacity重新进行上面的迭代,直至所有flow在迭代中获得的带宽都小于一个阈值时,算法结束,带宽分配完成。

让我们来分析这个算法并考虑如何加速该算法的执行速度。首先,对于一些bottleneck的link,流经其的flow早早就不能分配带宽了,因此如果发现在某个迭代中某条link能够分配的带宽已经小于阈值,那么在下一轮迭代,所有流经其的flow都不再考察,即使某些flow并不是以该link为bottleneck,因此,算法结束的条件可以改为当所有flow都不再考察的时候。这样对不对呢,让我们分析一下。以该link为bottleneck的flow自然不用说了,所谓的bottleneck就是能够获取的带宽最小的link,那么最小的link已经不能分配带宽了,该flow自然不再考察。但不是以该link作为bottleneck的flow呢,它们有更小带宽的link,但是如果该link不是你的bottleneck,已经不能分配带宽了,那就刚不用说更小带宽的link了,所以这些flow也应该不再考察。好,算法的讲解和分析就到这儿了,下面就是算法的实现,笔者采用的Java语言。

public Map<Integer, List<TrafficState>> run() {
		Map<Integer, List<TrafficState>> resultMap = new HashMap<Integer, List<TrafficState>>();
		int current = 0;
		// PrintWriter resultWriter = new PrintWriter(resultFileName);
		while (current < runtime) {
			List<Integer> runningFlowList = new ArrayList<Integer>();
			// the first traverse,add the new flows and remove the shopped flow
			for (int i = 0; i < graph.traffics.size(); i++) {
				Traffic currentTraffic = graph.traffics.get(i);
				int starttime = currentTraffic.start;
				if (starttime <= current && !currentTraffic.isStopped) {
					List<Integer> linksList = currentTraffic.links;
					if (currentTraffic.totlesize == 0) {
						// start a new flow
						currentTraffic.totlesize = currentTraffic.flowsize;
						currentTraffic.leftsize = currentTraffic.totlesize;
						for (Integer linkno : linksList) {
							graph.links.get(linkno).trafficList
									.add(currentTraffic);
						}
					}
					// calculate the transfer bytes in a epoch
					currentTraffic.epochsize = currentTraffic.speed
							* ((float) period / 1000);
					currentTraffic.leftsize -= currentTraffic.epochsize;

					if (currentTraffic.leftsize <= 0
							|| currentTraffic.end == current) {
						// no more flowsize or time is up,stop it
						currentTraffic.isStopped = true;
						for (Integer linkno : linksList) {
							graph.links.get(linkno).trafficList
									.remove(currentTraffic);
						}
					} else
						runningFlowList.add(i);
				}
			}
			// print the measurement
			if (printTimeSet.contains(current)) {
				List<TrafficState> stateList = new ArrayList<TrafficState>();
				for (Traffic traffic : graph.traffics) {
					//not the stop flows and the start ones just now
					if (!traffic.isStopped && traffic.totlesize != 0
							&& traffic.speed != 0) {
						TrafficState state = new TrafficState();
						state.setBytes(traffic.epochsize);
						state.setDestination(traffic.destination);
						state.setSource(traffic.source);
						state.setThruput(traffic.speed);
						String pathString = traffic.source;
						int lastNode = Integer.parseInt(traffic.source);
						for (Integer linkno : traffic.links) {
							if (lastNode == graph.links.get(linkno).source) {
								pathString += ","
										+ graph.links.get(linkno).target;
								lastNode = graph.links.get(linkno).target;
							} else {
								pathString += ","
										+ graph.links.get(linkno).source;
								lastNode = graph.links.get(linkno).source;
							}
							// pathString += "," +
							// graph.links.get(linkno).target;
						}
						state.setPathString(pathString);
						state.setStarttime(traffic.start);
						state.setFlowsize(traffic.flowsize);
						state.setEndtime(traffic.end);
						stateList.add(state);
					}
				}
				resultMap.put(current, stateList);
			}
			// initialize all the links and traffics
			for (Link link : graph.links) {
				link.leftCapacity = link.capacity;
			}
			for (Traffic traffic : graph.traffics) {
				traffic.speed = 0;
			}
			Set<Integer> finishedTrafficSet = new HashSet<Integer>();
			// the second traverse,set the throughput of each flow in next
			// iteration
			while (finishedTrafficSet.size() < runningFlowList.size()) {
				for (int i = 0; i < runningFlowList.size(); i++) {
					if (!finishedTrafficSet.contains(runningFlowList.get(i))) {
						Traffic currentTraffic = graph.traffics
								.get(runningFlowList.get(i));
						currentTraffic.increSpeed = Float.MAX_VALUE;
						Link minLink = null;
						for (Integer linkno : currentTraffic.links) {
							Link currentLink = graph.links.get(linkno);
							int existFlowNum = 0;// the number of exist flows
							for (Traffic traffic : currentLink.trafficList) {
								if (traffic.increSpeed != 0
										|| traffic.speed == 0) {
									existFlowNum++;
								}
							}
							float currentLinkSpeed = (float) currentLink.leftCapacity
									/ (float) existFlowNum;
							if (currentLinkSpeed < currentTraffic.increSpeed) {
								currentTraffic.increSpeed = currentLinkSpeed;
								minLink = currentLink;
							}
						}
						if (currentTraffic.increSpeed > 5)
							currentTraffic.speed += currentTraffic.increSpeed;
						else {
							currentTraffic.increSpeed = 0;
							if (minLink != null) {
								for (Traffic traffic : minLink.trafficList) {
									traffic.increSpeed = 0;
									finishedTrafficSet.add(graph.traffics
											.indexOf(traffic));
								}
							} else
								finishedTrafficSet.add(runningFlowList.get(i));
						}
					}
				}
				// link left capacity decrease the traffic increase throughput
				for (Link link : graph.links) {
					for (Traffic traffic : link.trafficList) {
						link.leftCapacity -= traffic.increSpeed;
					}
				}
			}
			current += period;
		}
		// resultWriter.close();
		return resultMap;
	}

Max-Min Fairness带宽分配算法

时间: 2024-10-06 09:02:36

Max-Min Fairness带宽分配算法的相关文章

平均分配算法

平均分配算法1.看到一遍老外写的并行运算,里面有个平均分配,感觉比较好,记录下 var count=11; for(int taskNumber = 0; taskNumber < cores; taskNumber++) { int seqno = taskNumber; var max = count * (seqno + 1) / cores; var j = count * seqno / cores; for (int i = j; i < max; i++) { } } //若11

操作系统: 最佳适配算法和邻近适配算法的模拟实现(内存分配算法)

实现动态分区的分配算法. (1) 最佳适配算法:选择内存空闲块中最适合进程大小的块分配. (2) 邻近适配算法:从上一次分配的地址开始查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程. 模拟添加进程的时候,假定内存是一块完整的空闲区,对于算法(1)来说,分配的时候遍历所有的空闲内存块,找出其中最适合的一块,注意此时内存分区的总块数可能已经发生了变化: 对于算法(2)来说,则需要从上次分配的内存块(使用变量记录即可)接着向下找到第一个满足条件的块即可,内存分区的总块可能也已经发生了变

聚合函数:sum,avg,max,min,count;模糊查询;排序

----聚合函数 --做计算 做统计 对null过滤:null是指不知道什么值,所以无法做计算--sum(参数):统计和--avg(参数):求平均值--max(参数):最大值--min(参数):最小值--count(参数):获取满足条件的记录数--1.获取学员总人数select COUNT(Email) from Student--2.获取最大的年龄值 年龄值越大,年龄越小 年龄值越小,年龄越大select MAX(BornDate) from Studentselect min(BornDat

合约广告中的流量分配算法

简介 合约广告是一种基于合约的广告模式,在线广告中的一种主流方式是担保式投放(Guaranteed Delivery,GD).GD是一种量优于质的广告投放方式,需要保证广告主能够获得在合约中约定的受众用户的流量.GD中,媒体的流量按照属性划分,媒体要给不同的广告主按照合同分配约定好的流量.Ad Server的准则是希望在每一次展现满足多个合约时,选择合适的广告主,以使得每个广告主效果最好,同时能够更有效的分配流量.如下图所示,supply为媒体方,提供流量,媒体的流量可以按照性别.年龄.地域划分

编译器后端,寄存器分配算法

寄存器分配,是通过将程序变量尽可能地分配到寄存器,从而提高程序执行速度的一种方法.寄存器是编译器优化中最为重要的问题之一(好的寄存器分配能够提高程序执行速度超过250%):也是编译器理论中最热点的研究领域之一(研究界已经提出来大量寄存器分配相关的算法). 1. 图着色(graph coloring)方法是解决寄存器分配问题最常用的方法. 利用相交图(interference graph)来表示程序变量的生命期是否相交,将寄存器分配给变量的问题,可以近似地看成是给相交图着色:相交图中,相交的节点不

MINI3内存分配算法

1 最差适应算法 2 #ifdef USING_WORST_FIT 3 { 4 //先找到第一个满足要求的空洞, 5 //再以第一个为标准寻找最适合的空洞. 6 //当最适合的空洞完全吻合 7 //就直接划给它,当空洞较大时就切割. 8 9 //首先注册目标指针.目标前一个指针.头指针 10 //记录目标大小和目前最适合大小 11 register struct hole *hp; 12 register struct hole *prevAim_ptr; 13 register struct

6.组函数(avg(),sum(),max(),min(),count())、多行函数,分组数据(group by,求各部门的平均工资),分组过滤(having和where),sql优化

 1组函数 avg(),sum(),max(),min(),count()案例: selectavg(sal),sum(sal),max(sal),min(sal),count(sal) from emp / 截图: 2 组函数和null在一起 案例:求员工的平均奖金 错误sql: select avg(comm) 方式1,sum(comm)/count(comm)方式2,sum(comm)/count(*) 方式3 from emp; 截图: 错误原因: select count(comm

线性扫描寄存器分配算法--相关论文

http://cs.au.dk/~mis/dOvs/slides/Kevin-linear-scan-reg-alloc.pdf ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF Greedy Register Allocation in LLVM 3.0 http://blog.llvm.org/2011/09/greedy-register-allocation-in-llvm-30.html http://lists.cs.uiuc.edu

day05 协程函数,递归函数,匿名函数lambda,内置函数map reduce filter max min zip sorted,匿名函数lambda和内置函数结合使用,面向过程编程与函数编程,模块与包的使用,re模块内置函数

基础篇 本章大纲: 协程函数 递归函数 匿名函数lambda 内置函数map reduce filter  max min zip sorted 匿名函数lambda和内置函数结合使用 面向过程编程与函数编程 模块与包的使用 re模块内置函数 一,协程函数 注意:函数先定义,后使用.这是函数第一原则.函数主要分为定义,调用 1.1,什么是协程函数 协程函数特点:yield变为表达式,可以通过g.send(value)传值,用send传值时协程函数需要初始化,也可以说是生成器函数的一种 1.2,协