@Override public List<Cloudlet> cloudletAssign(List<Cloudlet> cloudletList, List<Vm> vmList) { if (vmList != null || vmList.size() != 0) { List<Cloudlet> toAssignCloudletList = getToAssignCloudletList(cloudletList); // 初始化等待分配任务队列 if (toAssignCloudletList.size() < 1) { // 没有等待分配的任务,返回空列表 return null; // System.exit(0); } int m = vmList.size(); // 虚拟机数 int n = toAssignCloudletList.size(); // 即将分配任务列表数 int maxCloudletsWaitingLength = vQueueSize.getMaxLength(); // 子任务队列最大长度 List<Map<String, Integer>> vmWaitingQueueSizeList = initVmWaitingQueueSizeList(); // 初始化虚拟子队列队长列表 /* * Log.printLine("Queue size Print Before n=" + n); for (int i = 0;i * < m; i++) { Log.print(vmWaitingQueueSizeList.get(i).get("size") + * " "); } Log.printLine("\nvirQueueSize"); for (int i = 0; i < m; * i++) { Log.print(virQueueSize.get(i) + " "); } */ int i; int numFreeVm = m; // 空闲的vm数 List<Map<String, Integer>> tmpSizeList = updateTmpSizeList(-1, numFreeVm, vmWaitingQueueSizeList); // 临时队列 for (i = 0; i < n; i++) { // 分配任务到适合的虚拟机 int index = createAction(numFreeVm, tmpSizeList); int mSize = tmpSizeList.get(index).get("size"); if (mSize >= maxCloudletsWaitingLength) { // 若选择的队列满了,去掉这个队列,重新选择 if (numFreeVm > 1) { // 如果空闲的队列数还可以减为1或以上,则更新临时队列,即抛掉已满的队列 tmpSizeList = updateTmpSizeList(index, numFreeVm--, tmpSizeList); // System.out.println(numFreeVm); i--; continue; } else { // 所有虚拟机的等待队列都满了 Log.printLine("mSize=50 list(0):" + mSize); break; } // //寻找最空的队列作为要分配云任务的目的vm // for (int j = 0, tmp = maxCloudletsWaitingLength + 1; j < m; j++) { // if (tmp > vmWaitingQueueSizeList.get(j).get("size")) { // tmp = vmWaitingQueueSizeList.get(j).get("size"); // index = j; // } // } // mSize = vmWaitingQueueSizeList.get(0).get("size"); // //非排序手法获取最空队列的mSize // mSize = vmWaitingQueueSizeList.get(index).get("size"); // if (mSize >= maxCloudletsWaitingLength) { // Log.printLine("mSize=50 list(0):" + mSize); // break; // } } /* * Log.printLine("\nLOOP I:" + i); for (int j = 0; j < m; j++) { * Log.print(vmWaitingQueueSizeList.get(j).get("size") + " "); } */ // System.out.println("一个云任务分配Vm成功"); // int id = vmWaitingQueueSizeList.get(index).get("id"); int id = tmpSizeList.get(index).get("id"); // 被选中的虚拟机的id if (vQueueSize.increment(id)) { // 决断是否能正确分配到被选中的虚拟机中,虚拟机的子队列队长队长加一 tmpSizeList.get(index).put("size", ++mSize); // 更新临时虚拟机等待队列长度列表状态 for (int j = 0; j < m; j++) { // 更新虚拟机等待队列长度列表状态 if (vmWaitingQueueSizeList.get(j).get("id") == tmpSizeList.get(index).get("id")) { vmWaitingQueueSizeList.get(j).put("size", mSize); index = j; break; } } toAssignCloudletList.get(i).setVmId(id); // 将该任务分配给被选中的虚拟机 updateQList(index, m, vmList, vmWaitingQueueSizeList); // 更新Q值表 /* * Log.printLine("Cloudlet#" + * toAssignCloudletList.get(i).getCloudletId() + " vmid" + * toAssignCloudletList.get(i).getVmId() + "VM#" + id + * " size:" + vQueueSize.getQueueSize().get(id)); /* if * (mSize == 50) Log.printLine("size==50 Vm#" + id + * " Cloudlet#" + * toAssignCloudletList.get(i).getCloudletId() + " itsVmid " * + toAssignCloudletList.get(i).getVmId()); */ // Log.printLine("Two Sizes:" // + vQueueSize.getQueueSize().get(id) + " " // + vmWaitingQueueSizeList.get(index).get("size")); } else { // 被选中的虚拟机的等待队列已满 Log.printLine( index + "Index Assign Full Error!! Vm#" + id + " mSize:" + mSize + " vQueueSize:" + vQueueSize.getQueueSize().get(id)); System.exit(0); } } List<Cloudlet> assignedCloudletList = getAssignedCloudletList(i, toAssignCloudletList); // 获取被成功分配的任务列表 finishAssign(toAssignCloudletList); // 结束分配 Log.printLine( "Assign Finished! Left:" + getGlobalCloudletWaitingQueue().size() + " Success:" + assignedCloudletList.size()); return assignedCloudletList; } else { // 没有可用的虚拟机 Log.printLine("VmCloudletAssignerLearning No VM Error!!"); return null; } }
public class VmCloudletAssignerLearning extends VmCloudletAssigner { // 强化学习策略 private VirtualQueueSize vQueueSize = VirtualQueueSize.getInstance(); private static double gamma; // 强化学习算法的γ值 private static double alpha; // 强化学习算法的α值 private static double epsilon; // 强化学习算法的ε值 private static Map<String, Map<Integer, Double>> QList = new HashMap<String, Map<Integer, Double>>(); // Q值表 public VmCloudletAssignerLearning(double gamma, double alpha, double epsilon) { this.gamma = gamma; this.alpha = alpha; this.epsilon = epsilon; } @Override public List<Cloudlet> cloudletAssign(List<Cloudlet> cloudletList, List<Vm> vmList) { if (vmList != null || vmList.size() != 0) { List<Cloudlet> toAssignCloudletList = getToAssignCloudletList(cloudletList); // 初始化等待分配任务队列 if (toAssignCloudletList.size() < 1) { // 没有等待分配的任务,返回空列表 return null; // System.exit(0); } int m = vmList.size(); // 虚拟机数 int n = toAssignCloudletList.size(); // 即将分配任务列表数 int maxCloudletsWaitingLength = vQueueSize.getMaxLength(); // 子任务队列最大长度 List<Map<String, Integer>> vmWaitingQueueSizeList = initVmWaitingQueueSizeList(); // 初始化虚拟子队列队长列表 /* * Log.printLine("Queue size Print Before n=" + n); for (int i = 0;i * < m; i++) { Log.print(vmWaitingQueueSizeList.get(i).get("size") + * " "); } Log.printLine("\nvirQueueSize"); for (int i = 0; i < m; * i++) { Log.print(virQueueSize.get(i) + " "); } */ int i; int numFreeVm = m; // 空闲的vm数 List<Map<String, Integer>> tmpSizeList = updateTmpSizeList(-1, numFreeVm, vmWaitingQueueSizeList); // 临时队列 for (i = 0; i < n; i++) { // 分配任务到适合的虚拟机 int index = createAction(numFreeVm, tmpSizeList); int mSize = tmpSizeList.get(index).get("size"); if (mSize >= maxCloudletsWaitingLength) { // 若选择的队列满了,去掉这个队列,重新选择 if (numFreeVm > 1) { // 如果空闲的队列数还可以减为1或以上,则更新临时队列,即抛掉已满的队列 tmpSizeList = updateTmpSizeList(index, numFreeVm--, tmpSizeList); // System.out.println(numFreeVm); i--; continue; } else { // 所有虚拟机的等待队列都满了 Log.printLine("mSize=50 list(0):" + mSize); break; } // //寻找最空的队列作为要分配云任务的目的vm // for (int j = 0, tmp = maxCloudletsWaitingLength + 1; j < m; j++) { // if (tmp > vmWaitingQueueSizeList.get(j).get("size")) { // tmp = vmWaitingQueueSizeList.get(j).get("size"); // index = j; // } // } // mSize = vmWaitingQueueSizeList.get(0).get("size"); // //非排序手法获取最空队列的mSize // mSize = vmWaitingQueueSizeList.get(index).get("size"); // if (mSize >= maxCloudletsWaitingLength) { // Log.printLine("mSize=50 list(0):" + mSize); // break; // } } /* * Log.printLine("\nLOOP I:" + i); for (int j = 0; j < m; j++) { * Log.print(vmWaitingQueueSizeList.get(j).get("size") + " "); } */ // System.out.println("一个云任务分配Vm成功"); // int id = vmWaitingQueueSizeList.get(index).get("id"); int id = tmpSizeList.get(index).get("id"); // 被选中的虚拟机的id if (vQueueSize.increment(id)) { // 决断是否能正确分配到被选中的虚拟机中,虚拟机的子队列队长队长加一 tmpSizeList.get(index).put("size", ++mSize); // 更新临时虚拟机等待队列长度列表状态 for (int j = 0; j < m; j++) { // 更新虚拟机等待队列长度列表状态 if (vmWaitingQueueSizeList.get(j).get("id") == tmpSizeList.get(index).get("id")) { vmWaitingQueueSizeList.get(j).put("size", mSize); index = j; break; } } toAssignCloudletList.get(i).setVmId(id); // 将该任务分配给被选中的虚拟机 updateQList(index, m, vmList, vmWaitingQueueSizeList); // 更新Q值表 /* * Log.printLine("Cloudlet#" + * toAssignCloudletList.get(i).getCloudletId() + " vmid" + * toAssignCloudletList.get(i).getVmId() + "VM#" + id + * " size:" + vQueueSize.getQueueSize().get(id)); /* if * (mSize == 50) Log.printLine("size==50 Vm#" + id + * " Cloudlet#" + * toAssignCloudletList.get(i).getCloudletId() + " itsVmid " * + toAssignCloudletList.get(i).getVmId()); */ // Log.printLine("Two Sizes:" // + vQueueSize.getQueueSize().get(id) + " " // + vmWaitingQueueSizeList.get(index).get("size")); } else { // 被选中的虚拟机的等待队列已满 Log.printLine( index + "Index Assign Full Error!! Vm#" + id + " mSize:" + mSize + " vQueueSize:" + vQueueSize.getQueueSize().get(id)); System.exit(0); } } List<Cloudlet> assignedCloudletList = getAssignedCloudletList(i, toAssignCloudletList); // 获取被成功分配的任务列表 finishAssign(toAssignCloudletList); // 结束分配 Log.printLine( "Assign Finished! Left:" + getGlobalCloudletWaitingQueue().size() + " Success:" + assignedCloudletList.size()); return assignedCloudletList; } else { // 没有可用的虚拟机 Log.printLine("VmCloudletAssignerLearning No VM Error!!"); return null; } } private int createAction( int numVm, List<Map<String, Integer>> vmWaitingQueueSizeList) { // 生成选择虚拟机的动作,即获得想要的虚拟机号 int current_action; // 生成的动作,即要选择的虚拟机 int x = randomInt(0, 100); // 生成随机数[0,100] String state_idx = createState_idx(numVm, vmWaitingQueueSizeList); // 根据各虚拟机等待队列当前状态状态生成的Q值表行号 if (!QList.containsKey(state_idx)) { // 若Q值表中不存在这一行,则初始化这一行 initRowOfQList(state_idx, numVm); } // ///////////////// // System.out.println("\n输出state_idx\n" + state_idx); // ///////////////// // 根据随机数x选择生成动作的方式 if (((double) x / 100) < (1 - epsilon)) { // 生成动作方式1:利用(exploit) int umax = 0; double tmp = -1.0; for (int i = 0; i < numVm; i++) { // 选择当前状态行中Q值最大的列号,即要选择的虚拟机号 if (tmp < QList.get(state_idx).get(i)) { tmp = QList.get(state_idx).get(i); umax = i; } } if (tmp == -1) { // 利用动作没有正常进行 System.out.println("exploit没有正常进行。。!"); System.exit(0); } current_action = umax; } else { // 生成动作方式2:学习(explore) current_action = randomInt(0, numVm - 1); // 随机生成动作 } return current_action; } private void updateQList( int action_idx, int numVm, List<Vm> vmList, List<Map<String, Integer>> vmWaitingQueueSizeList) { // 更新Q值表 double sample = ((QCloudletSchedulerSpaceShared) vmList // 被选中的虚拟机中的任务平均等待时间 .get(action_idx) .getCloudletScheduler()) .getAverageWaitingTime(); if (sample <= 0.0) { // 若这个值为0,初始化为足够大的数 sample = 1000000.0; } double reward = 1.0 / sample; // 由被选中的虚拟机中的任务平均等待时间的倒数生成的reward值 String state_idx = createLastState_idx(action_idx, numVm, vmWaitingQueueSizeList); // 没有将当前任务分配到虚拟机队列时的状态行号 String next_state_idx = createState_idx(numVm, vmWaitingQueueSizeList); // 将当前任务分配到虚拟机队列后的状态行号 // ///////////////// // System.out.println(((QCloudletSchedulerSpaceShared) // vmList.get(action_idx).getCloudletScheduler()).getAverageWaitingTime()+" "+reward); System.out.println("\n输出state_idx\n" + state_idx); System.out.println("\n输出next_state_idx\n" + next_state_idx); // ///////////////// if (!QList.containsKey(next_state_idx)) { // 若更新后的行不存在于Q值表中,则初始化它 initRowOfQList(next_state_idx, numVm); } double QMaxNextState = -1.0; for (int i = 0; i < numVm; i++) { // 获取更新后的状态行的最大值 if (QMaxNextState < QList.get(next_state_idx).get(i)) { QMaxNextState = QList.get(next_state_idx).get(i); } } double QValue = QList.get(state_idx).get(action_idx) // Q值表Q值更新的主要公式 + alpha * (reward + gamma * QMaxNextState - QList.get(state_idx).get(action_idx)); // System.out.println(QList.get(state_idx).get(action_idx)+" "+alpha+" "+reward // +" "+gamma+" "+QMaxNextState+" "+QList.get(state_idx).get(action_idx)+" "+QValue); QList.get(state_idx).put(action_idx, QValue); } private int randomInt(int min, int max) { // random[min,max] 可取min,可取max if (min == max) { return min; } Random random = new Random(); return random.nextInt(max) % (max - min + 1) + min; } private String createLastState_idx( int action_idx, int numVm, // 生成更新前的状态行行号 List<Map<String, Integer>> vmWaitingQueueSizeList) { String state_idx = ""; for (int i = 0; i < numVm; i++) { // 根据虚拟机数目获得列数并循环处理 if (i == action_idx) { // 若该行为变化的行,则获取它变化前的状态 state_idx += "-" + (vmWaitingQueueSizeList.get(i).get("size").intValue() - 1); } else { // 没有变化的行 state_idx += "-" + vmWaitingQueueSizeList.get(i).get("size").intValue(); } } return state_idx; } private String createState_idx( int numVm, List<Map<String, Integer>> vmWaitingQueueSizeList) { // 生成当前状态行行号 String state_idx = ""; for (int i = 0; i < numVm; i++) { // 根据虚拟机数目获得列数并循环处理 state_idx += "-" + vmWaitingQueueSizeList.get(i).get("size").intValue(); } return state_idx; } private void initRowOfQList(String state_idx, int numColumn) { // 初始化Q值表的行 QList.put(state_idx, new HashMap<Integer, Double>()); for (int i = 0; i < numColumn; i++) { QList.get(state_idx).put(i, 0.0); // 赋初值为0 } } private List<Map<String, Integer>> updateTmpSizeList( int index, int numFreeVm, // 更新临时虚拟机等待队列长度列表的状态 List<Map<String, Integer>> originSizeList) { List<Map<String, Integer>> tmp = new ArrayList<Map<String, Integer>>(); for (int j = 0; j < numFreeVm; j++) { if (index == -1 || originSizeList.get(j).get("id") != originSizeList.get(index).get("id")) { // 将被选中的虚拟机(等待队列已满的虚拟机) tmp.add(originSizeList.get(j)); // 从该临时列表中去掉 } } return tmp; } }