WorkflowSim中VerticalClustering(垂直聚合)的代码解读
WorkflowSim内置VerticalClustering算法
WorkflowSim作为一个较为完善的工作流仿真平台,内置有许多算法程序,其中包括了任务聚类算法。
WorkflowSim当中有example和source包,里面分别有内置的例子和对应的资源文件:在source包内有clustering的子包,其中包括了几个运用较广泛的任务聚类算法程序。本文主要介绍内置的垂直聚类–VerticalClustering算法。
- 算法所在位置:
算法class文件存放在source源文件夹下的org.workflowsim.clustering包中,位置如图所示:
- 算法作用:
将“管道任务”合并为一个任务,何为“管道任务”?简单来说,两个相连任务,若父任务只有一个子任务,且该子任务只有这一个父任务,那么这两个任务就是“管道任务”,依此类推可以得到数量大于2的“管道任务”的定义。
为何要进行聚类合并呢?因为在工作流的调度过程中,若相连任务被安排在不同的虚拟机上进行调度,就必须要将上一个任务的执行数据传输到下一个任务所在的虚拟机上,则会增加任务间的通信传输花费,而对于“管道任务”来说,安排在统一虚拟机上调度则能很好地避免了这种浪费的产生。
下图就是对这种“管道任务”进行聚合的一个示意图:
3.算法代码
垂直聚类的思想十分的简单,即判断是否满足“管道任务”的定义,满足的则通过加入一个链表中,通过定义的addTasks2Job(List) 来进行合并。
那么直接上代码,部分注释已经标注在代码中。
package org.workflowsim.clustering;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.workflowsim.Task;
import org.workflowsim.utils.Parameters;
/**
* VerticalClustering merges tasks at the same pipeline
*/
public class VerticalClustering extends BasicClustering {
/* The maximum depth to explore. */
private final int mDepth;//声明最大深度
/* The checkpoint map. */
private final Map<Integer, Boolean> mHasChecked;//声明映射mHasChecked<整数,逻辑数>
/**
* Initialize a VeriticalClustering object
*
* @param depth depth
*/
public VerticalClustering(int depth) {
super();//调用父类BasicClustering的主类中几个参数
this.mDepth = depth;
this.mHasChecked = new HashMap<>();
}
/**
* Sets the checkpoint of a task
*
* @param index id of a task
*/
private void setCheck(int index) {
//定义setCheck,设置任务的检查点,检查键index
if (mHasChecked.containsKey(index)) {
//如果mHasChecked映射的键值对中有键index,则删去对应的映射
mHasChecked.remove(index);
}
mHasChecked.put(index, true);//加入index和标记为true的键值对映射
}
/**
* Gets the checkpoint of a task
*
* @param index id of a task
* @return
*/
private boolean getCheck(int index) {
//定义getCheck,检查映射中键为index的键值对是否被检查过
if (mHasChecked.containsKey(index)) {
//如果mHasChecked中有键位index键值对,则输出对应的逻辑值并跳出
return mHasChecked.get(index);
}
return false;//否则输出false
}
/**
* The main function
*/
@Override
public void run() {
if (mDepth > 0) {
/**
* Specially for Montage workflow since it has duplicate edges
*/
if (Parameters.getReduceMethod().equals("montage")) {
//如果缩减方法等于"montage",则删除montage中重复的
removeDuplicateMontage();
}
Task root = super.addRoot();//调用父大类的addRoot,给根节点任务加一个统一的t entry--root
Task node;//声明node任务
List<Task> taskList = new ArrayList<>();
Stack<Task> stack = new Stack<>();//新建栈
stack.push(root);//栈中填入root
while (!stack.empty()) {
//当栈不为空时
node = (Task) stack.pop();//栈顶输出的任务赋值为node
if (!getCheck(node.getCloudletId())) {
//如果检查出node的ID未被检查过
setCheck(node.getCloudletId());//设置node的ID已被检查
int pNum = node.getParentList().size();//pNum为node的父类任务个数
int cNum = node.getChildList().size();//cNum为node的子类任务个数
for (Task cNode : node.getChildList()) {
//对于node的子类,依此填放入栈中
stack.push(cNode);
}
if (pNum == 0) {
//如果无父类,即当为root,则跳过
//root skip it
}
else if (pNum > 1) {
//若node不止一个父类
if (cNum > 1 || cNum