首先理解雲計算里,資源調度的含義:
看了很多雲計算資源調度和任務調度方面的論文,發現很多情況下這兩者的意義是相同的,不知道這兩者是同一件事的不同表述還是我沒分清吧,任務調度或者資源調度大概就是講這樣一件事情:
用戶有n個計算任務(Task),{t1,t2,t3,...tm},將這n個任務分配到m個資源(其實就是指虛擬機,Virtual Machine)上,用這m個資源來計算這n個任務(注意,一般n>m,且很多時候n>>m),直到所有任務都計算完成。如何分配使得這n個任務的總的計算時間最少?這里,總的計算時間是指,最后一個計算完成的任務的完成時刻,而不是每個任務的計算時間求和。
關於這個問題的准確的描述,引用王登科 李 忠《基於粒子群優化與蟻群優化的雲計算任務調度算法》的描述:
舉個例子:
假設某雲計算系統的一台主機上運行了3個虛擬機{VM0,VM1,VM2},它們的計算能力(即單位時間內能夠執行的指令數量,CloudSim里用mips來衡量)分別是{3000,1000,500}.
某用戶有5個計算任務{t0,t1,t2,t3,t4},任務大小(就是要執行的指令數量,CloudSim里用length來表示)分別是{4000,2000,2500,10000,500},提交到cloudsim系統中進行模擬運算。
根據cloudsim默認的調度策略,產生的調度結果是:VM0={t0,t3},VM1={t1,t4},VM2={t2}
由於VM0,VM1,VM2並行執行,互不影響,因此
VM0上的執行時間為:(t0+t3)/VM0 mips=(4000+10000)/3000=4.667,
VM1上的執行時間為:(t1+t4)/VM1 mips=(2000+500)/1000=2.5,
VM2上的執行時間為:t2/VM2 mips=2500/500=5。
因此這種調度方案的總的運行時間為max{4.667,2.5,5}=5。
其中,這種調度方案,可用一個二維表來表示:
這個表跟上面的那個X表行和列對調了一下,但意思一樣,注意觀察每一行都只有一個1,表示每個任務只能分配給一個資源(虛擬機)進行計算,但1個資源(虛擬機)可能計算不止一個任務。
如果運用遺傳算法或其他進化算法,需要對每個解(對應這里的每一種調度方案),計算它的適應度值(這里的適應度函數就是每種調度方案對應的任務完成時間),選擇適應度值最好的作為最優,進行下一次迭代。
如何把一種調度方案表示為一個解,如何計算解的適應度值?可以參考:非常好的理解遺傳算法的例子
這里,可以把每一行的二進制數化成一個十進制整數,每個數取值只能取{20,21,22,...,2m-1}中的任意一個,共n個任務,即有n個這樣的數,這就是遺傳算法當中的所謂編碼,即用一種方式來把調度方案表示成解(上面的調度方案可表示為42142,每一位數表示資源的分配結果)。
或者用資源的編號組合來表示調度方案:n個任務,每個任務從[0,m-1]之間的整數任取一個,那么一個調度方案就是一個1*n維的向量,如上例的調度方案可表示為 [0,1,2,0,1]
而把解轉化成調度方案就是所謂解碼。
如何把把自己的算法,如遺傳算法運用到Cloudsim中去?最簡單的辦法是調用DatacenterBroker的 bindCloudletToVM(int cloudletId, int vmId),通過遺傳算法的計算結果用代碼動態調用該方法,將任務與資源進行綁定,這種綁定就是任務的調度的體現。
如何理解遺傳算法本身,請參考:遺傳算法(Genetic Algorithm)
說到這,我有點疑問,按照上面的調度表格,每個任務必須要為它分配一個資源,且只能分配一個資源,那調度方案的總個數其實是可以窮舉的,因為n個任務,m個資源,每個任務都有m種選擇,一共就是mn種調度方案。所以最佳調度方案其實是很容易窮舉算出來的,為什么還要用遺傳算法之類的進化算法來算呢?可能是當n足夠大之后,mn這個值太大,調度方案太多,導致窮舉太耗時,才需要這些調度算法吧。
Cloudsim模擬的實例代碼:
public static void RunSimulation(int []taskLength,int taskNum) { System.out.println("Starting to run simulations..."); try { int num_user = 1; // number of cloud users Calendar calendar = Calendar.getInstance(); boolean trace_flag = false; CloudSim.init(num_user, calendar, trace_flag); //下面創建的datacenter是用來運行任務的物理硬件,是必需的,否則不能運行。它被創建之后看似沒有調用,好像沒啥用,其實DataCenter構造函數把它與CloudSim類進行了綁定,所以能夠發揮作用 @SuppressWarnings("unused") Datacenter datacenter0 = createDatacenter("Datacenter_0"); // #3 step: Create Broker DatacenterBroker broker = createBroker(); int brokerId = broker.getId(); // #4 step: Create one virtual machine vmlist = new ArrayList<Vm>(); // VM description long size = 10000; // image size (MB) int ram = 512; // vm memory (MB) long bw = 1000; int pesNumber = 1; // number of cpus String vmm = "Xen"; // VMM name double mips=5000;//mips是虛擬機的cpu處理速度,cloudlet的length/虛擬機mips=任務執行所需時間 //所有虛擬機的mips之和不能超過datacenter中定義的主機的物理cpu的mips之和,而虛擬cpu的mips的最大值也不能超過物理cpu的最大值,否則虛擬機將創建失敗。 Vm vm1 = new Vm(0, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerSpaceShared()); mips=2500; Vm vm2 = new Vm(1, brokerId, mips, pesNumber, ram, bw, size, vmm,new CloudletSchedulerTimeShared()); mips=2500; Vm vm3 = new Vm(2, brokerId, mips, pesNumber, ram, bw, size, vmm,new CloudletSchedulerTimeShared()); mips=1500; Vm vm4 = new Vm(3, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerSpaceShared()); mips=1000; Vm vm5 = new Vm(4, brokerId, mips, pesNumber, ram, bw, size, vmm, new CloudletSchedulerSpaceShared()); // add the VMs to the vmList vmlist.add(vm1); vmlist.add(vm2); vmlist.add(vm3); vmlist.add(vm4); vmlist.add(vm5); // submit vm list to the broker broker.submitVmList(vmlist); // #5 step: Create cloudlets cloudletList = new ArrayList<Cloudlet>(); // Cloudlet properties int id = 0; pesNumber = 1; long fileSize = 250; long outputSize = 10000000; UtilizationModel utilizationModel = new UtilizationModelFull(); for(int i=0;i<taskNum;i++) { //Cloudlet構造函數的一個參數為任務id,第二個參數為任務長度(指令數量) Cloudlet task = new Cloudlet(i, taskLength[i], pesNumber, fileSize, outputSize, utilizationModel, utilizationModel, utilizationModel); task.setUserId(brokerId); cloudletList.add(task); } broker.submitCloudletList(cloudletList); for(int i=0;i<taskNum;i++) { //下面的兩行代碼用於把任務綁定到指定的虛擬機上,兩行代碼效果是一樣的 //如果需要用自己實現的算法來進行資源調度,則可以在算法中動態調用DataCenterBroker.bindCloudletToVm()方法或者Cloudlet.setVmId()方法 //broker.bindCloudletToVm(cloudletList.get(i).getCloudletId(),vm1.getId()); cloudletList.get(i).setVmId(vm1.getId()); } bindAllTaskToSameVM(cloudletList,vm1.getId()); CloudSim.startSimulation(); // Final step: Print results when simulation is over List<Cloudlet> newList = broker.getCloudletReceivedList(); CloudSim.stopSimulation(); for(Vm vm:vmlist) { System.out.println(String.format("vm id= %s ,mips = %s ",vm.getId(),vm.getMips())); } printCloudletList(newList); System.out.println("CloudSim simulation is finished!"); } catch (Exception e) { e.printStackTrace(); System.out.println("The simulation has been terminated due to an unexpected error"); } } private static Datacenter createDatacenter(String name) { List<Host> hostList = new ArrayList<Host>(); List<Pe> peList = new ArrayList<Pe>(); //創建五個cpu,mips為cpu的處理速度 int mips = 5000; peList.add(new Pe(0, new PeProvisionerSimple(mips))); // need to store Pe id and MIPS Rating mips = 2500; peList.add(new Pe(1, new PeProvisionerSimple(mips))); // need to store mips = 2500; peList.add(new Pe(2, new PeProvisionerSimple(mips))); // need to store mips = 1500; peList.add(new Pe(3, new PeProvisionerSimple(mips))); // need to store mips = 1000; peList.add(new Pe(4, new PeProvisionerSimple(mips))); // need to store int hostId = 0; int ram = 4096; // host memory (MB) long storage = 10000000; // host storage int bw = 10000; hostList.add(new Host(hostId, new RamProvisionerSimple(ram), new BwProvisionerSimple(bw), storage, peList, new VmSchedulerTimeShared(peList))); String arch = "x86"; // system architecture String os = "Linux"; // operating system String vmm = "Xen"; double time_zone = 10.0; // time zone this resource located double cost = 3.0; // the cost of using processing in this resource double costPerMem = 0.05; // the cost of using memory in this resource double costPerStorage = 0.001; // the cost of using storage in this // resource double costPerBw = 0.001; // the cost of using bw in this resource //we are not adding SAN devices by now LinkedList<Storage> storageList = new LinkedList<Storage>(); DatacenterCharacteristics characteristics = new DatacenterCharacteristics( arch, os, vmm, hostList, time_zone, cost, costPerMem, costPerStorage, costPerBw); // 6. Finally, we need to create a PowerDatacenter object. Datacenter datacenter = null; try { datacenter = new Datacenter(name, characteristics, new VmAllocationPolicySimple(hostList), storageList, 0); } catch (Exception e) { e.printStackTrace(); } return datacenter; } private static DatacenterBroker createBroker() { DatacenterBroker broker = null; try { broker = new DatacenterBroker("Broker"); } catch (Exception e) { e.printStackTrace(); return null; } return broker; } private static void printCloudletList(List<Cloudlet> list) { int size = list.size(); Cloudlet cloudlet; String indent = " "; System.out.println(); System.out.println("========== OUTPUT =========="); System.out.println("Cloudlet ID" + indent + "STATUS" + indent + "Data center ID" + indent + "VM ID" + indent +"CloudletLength"+indent+ "Time" + indent + "Start Time" + indent + "Finish Time"); DecimalFormat dft = new DecimalFormat("###.##"); for (int i = 0; i < size; i++) { cloudlet = list.get(i); Log.print(indent + cloudlet.getCloudletId() + indent + indent); if (cloudlet.getStatus()== Cloudlet.SUCCESS) { Log.print("SUCCESS"); System.out.println(indent +indent + indent + cloudlet.getResourceId() + indent + indent + indent + cloudlet.getVmId() + indent + indent + cloudlet.getCloudletLength() + indent + indent+ indent + indent + dft.format(cloudlet.getActualCPUTime()) + indent + indent + dft.format(cloudlet.getExecStartTime()) + indent + indent + dft.format(cloudlet.getFinishTime())); } } }
本文鏈接:http://www.cnblogs.com/aaronhoo/p/6218024.html
參考資料:
《基於粒子群優化與蟻群優化的雲計算任務調度算法》王登科 李 忠
碩士論文《基於雲計算環境下資源調度算法研究》 鄔海艷
http://blog.csdn.net/b2b160/article/details/4680853/
http://blog.chinaunix.net/uid-27105712-id-3886077.html