-
Notifications
You must be signed in to change notification settings - Fork 53
/
put_flavors_to_servers.cpp
135 lines (123 loc) · 5.3 KB
/
put_flavors_to_servers.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "Server.h"
#include <unordered_map>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
//如果关心的资源是CPU则为true,如果关心的资源是内存则为False
#define CPU true
#define MEM false
using namespace std;
///使用模拟退火算法找最佳的虚拟机放置方式
///输入参数:
///map_predict_num_flavors:上一步预测出来的各种虚拟机数量,key是虚拟机名称,value是虚拟机数量
///map_flavor_cpu_mem:程序输入的虚拟机类型数据,key为虚拟机名称,value是虚拟机类型(包括name,cpu,mem字段)
///server_mem && server_cpu:程序输入的服务器参数,CPU和内存大小
///CPUorMEM:是使CPU利用率最高还是使内存利用率最高
///输出参数:
///res_servers:存放有计算出的最优服务器中虚拟机存放方式,可通过成员flavors访问每个服务器中存放的虚拟机
vector<Server> put_flavors_to_servers(unordered_map<string, int> map_predict_num_flavors,
unordered_map<string, Flavor> map_flavor_cpu_mem,int server_mem, int server_cpu, bool CPUorMEM) {
vector<Flavor> vec_flavors; //vector用于存放所有预测出来的flavor
for (auto element : map_predict_num_flavors) {
//将预测出来的所有虚拟机都加入到vec_flavors中
while (element.second-- != 0) {
vec_flavors.push_back(map_flavor_cpu_mem[element.first]);
}
}
//=========================================================================
//模拟退火算法找最优解
double min_server = vec_flavors.size() + 1;
vector<Server> res_servers; //用于存放最好结果(服务器使用数量最少)
double T = 100.0; //模拟退火初始温度
double Tmin = 1; //模拟退火终止温度
double r = 0.9999; //温度下降系数
vector<int> dice; //骰子,每次随机投掷,取vector前两个变量作为每次退火需要交换顺序的虚拟机
for (int i = 0; i < vec_flavors.size(); i++) {
dice.push_back(i);
}
while (T > Tmin) {
//投掷骰子,如vector前两个数为3和9,则把vec_flavors[3]和vec_flavors[9]进行交换作为新的flavors顺序
std::random_shuffle(dice.begin(), dice.end());
auto new_vec_flavors = vec_flavors;
std::swap(new_vec_flavors[dice[0]], new_vec_flavors[dice[1]]);
//把上一步计算出来的虚拟机尝试加入到服务器中
//先使用一个服务器用于放置虚拟机
vector<Server> servers;
Server firstserver(server_mem, server_cpu);
servers.push_back(firstserver);
//放置虚拟机主要逻辑
//如果当前所有服务器都放不下虚拟机,就新建一个服务器用于存放
for (auto element : new_vec_flavors) {
auto iter = servers.begin();
for (; iter != servers.end(); ++iter) {
if (iter->put_flavor(element)) {
break;
}
}
if (iter == servers.end()) {
Server newserver(server_mem, server_cpu);
newserver.put_flavor(element);
servers.push_back(newserver);
}
}
//计算本次放置虚拟机耗费服务器评价分数(double型)
//如果使用了N个服务器,则前N-1个服务器贡献分数为1,第N个服务器分数为资源利用率
//模拟退火就是得到取得分数最小的放置方式
double server_num;
//对于题目关心CPU还是MEM,需要分开讨论,资源利用率计算方法不同
if (CPUorMEM == CPU)
server_num = servers.size() - 1 + servers.rbegin()->get_cpu_usage_rate();
else
server_num = servers.size() - 1 + servers.rbegin()->get_mem_usage_rate();
//如果分数更低,则保存结果
if (server_num < min_server) {
min_server = server_num;
res_servers = servers;
vec_flavors = new_vec_flavors;
}
//如果分数更高,则以一定概率保存结果,防止优化陷入局部最优解
else {
if (exp((min_server - server_num) / T) > rand() / RAND_MAX) {
min_server = server_num;
res_servers = servers;
vec_flavors = new_vec_flavors;
}
}
T = r * T; //一次循环结束,温度降低
}
return res_servers;
}
int main() {
//程序运用例子
//预测出来的各种虚拟机数量
unordered_map<string, int> map_predict_num_flavors;
map_predict_num_flavors["flavor1"] = 30;
map_predict_num_flavors["flavor2"] = 40;
map_predict_num_flavors["flavor3"] = 20;
map_predict_num_flavors["flavor4"] = 10;
map_predict_num_flavors["flavor5"] = 25;
//各种虚拟机参数
unordered_map<string, Flavor> map_flavor_cpu_mem;
map_flavor_cpu_mem["flavor1"] = Flavor("flavor1", 1, 1);
map_flavor_cpu_mem["flavor2"] = Flavor("flavor2", 1, 2);
map_flavor_cpu_mem["flavor3"] = Flavor("flavor3", 1, 4);
map_flavor_cpu_mem["flavor4"] = Flavor("flavor4", 2, 2);
map_flavor_cpu_mem["flavor5"] = Flavor("flavor5", 2, 4);
//服务器资源相关信息
int server_cpu = 56;
int server_mem = 128;
bool CPUorMEM = CPU;
//调用模拟退火算法找到最优放置方法
vector<Server> servers = put_flavors_to_servers(map_predict_num_flavors, map_flavor_cpu_mem, server_mem, server_cpu, CPUorMEM);
//输出各个服务器里面分别放置了哪些虚拟机
int server_count = 1;
for (auto element : servers) {
cout << server_count++ << " ";
for (auto flavor : element.flavors) {
std::cout << flavor.name << " " << 1 << " ";
}
cout << endl;
}
return 0;
}