经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
2021华为软件精英挑战赛(C/C++实现)-苦行僧的实现过程
来源:cnblogs  作者:流星斩月  时间:2021/3/29 9:14:15  对本文有异议

  下面给出2021华为软件精英挑战赛参与的整个过程,虽然成绩不是很好,但是也是花了一些时间的,希望后面多多学习,多多进步。

  代码已经上传到了Github上:https://github.com/myFrank/huawei_test,代码给出了简易的虚拟机迁移思路和服务器初始化购买及服务器的扩容实现。

1、赛题简介

  区域初赛赛题的考核内容,要求选手根据赛题的相关条件,进行云资源的合理规划与调度,在满足用户所有请求的前提下,减少运营、硬件成本开销。

2、题目定义

2.1、服务器

2.1.1、服务器类型

  在公有云的运营场景中,我们的数据中心可以选购的服务器类型有多种,以下是目前公有云常用的一些服务器类型。

2.1.2、NUMA 架构

  目前主流的服务器都采用了非统一内存访问(NUMA)架构,你可以理解为每台服务器内部都存在两个 NUMA 节点:A 和 B(下文中提到的节点均指 NUMA 节点)。服务器拥有的资源(CPU 和内存)均匀分布在这两个节点上。以 NV603 为例,其 A、B 两个节点分别包含 46C 和 162G 的资源。保证服务器的CPU 核数和内存大小均为偶数。

2.1.3、服务器成本

  数据中心使用每台服务器的成本由两部分构成:硬件成本和能耗成本。硬件成本是在采购服务器时的一次性支出,能耗成本是后续服务器使用过程中的持续支出。为了便于计算,我们以天为单位计算每台服务器的能耗成本。若一台服务器在一天内处于关机状态,则其不需要消耗任何能耗成本,否则我们需要支出其对应的能耗成本。

2.1.4、虚拟机类型

  我们面向用户提供了多种类型的虚拟机售卖服务,用户可以根据自己的需求来自由选购,以下是一些常用的虚拟机类型。 

2.1.5、单节点/双节点部署

  由于服务器存在两个节点,对应的虚拟机也存在两种部署方式:单节点部署或双节点部署。单节点部署指的是一台虚拟机所需的资源(CPU和内存)完全由主机上的一个节点提供;双节点部署指的是一台虚拟机所需的资源(CPU 和内存)必须由一台服务器的两个节点同时提供,并且每个节点提供总需求资源的一半。例如:c3.8xlarge.2 类型的虚拟机需要被部署在一台服务器的 A和 B 两个节点上,A、B 节点分别提供 16C,32G 资源。请注意,一种类型的虚拟机是单节点部署还是双节点部署与其规格没有必然联系,但是双节点部署的虚拟机保证其 CPU 和内存需求量都是偶数。 

2.2、 资源规划和调度

2.2.1、容量约束

  服务器可以用来容纳用户的虚拟机,但是服务器上的任意一个节点(A和 B)上的资源负载(CPU 和内存)均不能超过其容量上限。

2.2.2、请求类型

  用户的请求共分为两种类型:创建请求和删除请求。创建请求表示用户向公有云平台提交的一个创建虚拟机的请求;删除请求表示用户提交的删除一台之前创建的虚拟机的请求。

2.2.3、请求序列

  由一系列请求构成的序列。题目会给出接下来若干天中每一天用户的请求序列,根据每天的请求序列,你需要进行相应的资源规划和调度。

2.2.4、数据中心扩容

  在得知了一天的请求序列后,你可以在实际进行调度前进行一次数据中心扩容。即购买一些新的服务器来容纳后续用户请求的虚拟机,同时你需
要付出所购买服务器相应的硬件成本。你需要指定购买哪些类型的服务器以及购买的数量。初始时你没有任何服务器。

2.2.5、虚拟机迁移

  在完成扩容后,在处理每一天的新请求之前,你还可以对当前存量虚拟机进行一次迁移,即把虚拟机从一台服务器迁移至另一台服务器。对于单节
点部署的虚拟机,将其从一台服务器的 A 节点迁移至 B 节点(或反之)也是允许的。迁移的目的服务器和节点必须有足够的资源容纳所迁移的虚拟机。迁移的虚
拟机总量不超过当前存量虚拟机数量的千分之五。即假设当前有 n 台存量虚拟机,每天你可以迁移的虚拟机总量不得超过 5n/1000 向下取整。

2.2.6、部署虚拟机

  在完成扩容和迁移之后,你需要按顺序处理当天所有的新请求。对于每一个创建虚拟机的新请求,你要为虚拟机指定一台服务器进行部署。若虚拟机是单节点部署的,你还需要指明部署在服务器的 A 节点还是 B 节点。处理请求的过程中,任意一台服务器上每个节点容纳的虚拟机资源总和都不能超出节点本身的资源容量(指 CPU 和内存两个维度)。

3、赛题实现(C/C++实现)

  由于服务器的资源是NUMA均匀分布,所以我们每个服务器CPU核数 service_cpu和内存大小 service_mem,则它在A,B两个节点均分后,各有service_cpu/2 个cpu核数和 service_mem/2 大小的内存。

3.1、下面给出赛题定义的结构体数据类型:

  1. 1 /*
  2. 2 记录每天添加/删减的虚拟机CPU及内存数量及单双核数量-分单双节点部署(用结构体)
  3. 3 */
  4. 4 struct _per_day_VmTotal_info {
  5. 5
  6. 6 int deployed_Vm_number = 0;
  7. 7
  8. 8 int Per_Day_VmTotal_CPU = 0;
  9. 9 int Per_Day_VmTotal_MEM = 0;
  10. 10
  11. 11 int Per_Day_VmTotal_DoubleNodeCPU = 0;
  12. 12 int Per_Day_VmTotal_DoubleNodeMEM = 0;
  13. 13
  14. 14
  15. 15 int Per_Day_VmTotal_SingeNode = 0;
  16. 16 int Per_Day_VmTotal_DoubleNode = 0;
  17. 17
  18. 18 }per_day_VmTotal_info;
  19. 19
  20. 20
  21. 21 /*
  22. 22 记录每天购买的服务器类型,包括
  23. 23 购买服务器的类型
  24. 24 服务器ID(编号从0开始,每增加一台编号增加1
  25. 25 服务器用途(目前用于为虚拟机单双节点部署flag,0表示此编号服务器用于单节点部署
  26. 26 1表示此编号服务器用于双节点部署
  27. 27 服务器A节点的剩余CPU核数(初始为total cpu/2)
  28. 28 服务器B节点的剩余CPU核数
  29. 29 服务器A节点的剩余MEM(初始为total mem/2)
  30. 30 服务器B节点的剩余MEM
  31. 31
  32. 32 还需要记录每个服务器上所负载的虚拟机的ID,为了migration
  33. 33 */
  34. 34 struct _purchase_service_info {
  35. 35 string purchase_service_type;
  36. 36
  37. 37 int purchased_Service_number;
  38. 38
  39. 39 /*除了记录服务器ID(注意服务器ID对应的信息可以从其他参数导出)
  40. 40 还需要记录每个服务器上所负载的虚拟机的ID,为了migration*/
  41. 41 unordered_map<int, vector<int>> purchase_service_ID_Info;
  42. 42 /*
  43. 43 purchase_service_ID_Info[i][j] :s
  44. 44 其中i表示 购买的服务器序号,目前是和服务器ID一致
  45. 45 其中j = 0时,存储服务器ID ; j = 1 2 3 时,表示搭建的虚拟机编号
  46. 46 */
  47. 47
  48. 48 //vector<int> purchase_service_ID;
  49. 49 vector<int> purchase_service_useflag;
  50. 50 vector<int> purchase_service_nodeA_remainCPU;
  51. 51 vector<int> purchase_service_nodeB_remainCPU;
  52. 52 vector<int> purchase_service_nodeA_remainMEM;
  53. 53 vector<int> purchase_service_nodeB_remainMEM;
  54. 54
  55. 55 }purchase_service_info;
  56. 56
  57. 57
  58. 58 /*
  59. 59 解析txt文件时,将可供购买的服务器类型信息解析保存
  60. 60 (型号,cpu,内存大小,硬件成本,每日能耗成本)
  61. 61 */
  62. 62 struct _server_info_stu {
  63. 63 string serverType;
  64. 64 string cpuCores;
  65. 65 string memorySize;
  66. 66 string serverCost;
  67. 67 string powerCost;
  68. 68 };
  69. 69
  70. 70 /*
  71. 71 解析txt文件时,将可售卖虚拟机类型信息解析保存
  72. 72 (型号,cpu核数,内存大小,是否双节点部署)
  73. 73 */
  74. 74 struct _vm_info_stu {
  75. 75 string vmType;
  76. 76 string vmCpuCores;
  77. 77 string vmMemory;
  78. 78 string vmTwoNodes;
  79. 79 };
  80. 80
  81. 81 struct _userVm_requestAdd_info {
  82. 82 string op;
  83. 83 string reqVmType;
  84. 84 string reqId;
  85. 85 };
  86. 86
  87. 87 struct _userVm_requestDel_info {
  88. 88 string op;
  89. 89 string reqId;
  90. 90 };

3.2、服务器虚拟机数据处理

  我采用的是unordered_map来存储每种NUMA服务器的信息,虚拟机为了方便匹配服务器,设计的数据结构如下:

  1. 1 // 服务器信息
  2. 2 unordered_map<string,vector<int>> serverInfos;
  3. 3 // 虚拟机信息
  4. 4 unordered_map<string,vector<int>> vmInfos;

  在解析training-1/2.txt文件时,将可供购买的服务器类型和用户可以创建的虚拟机类型信息解析保存。

  1. 1 void generateServer(_server_info_stu *server_info_stu)
  2. 2 {
  3. 3 string _serverType = "";
  4. 4 for (int i = 1; i < server_info_stu->serverType.size() - 1; i++) {
  5. 5 _serverType += server_info_stu->serverType[i];
  6. 6 }
  7. 7
  8. 8 int _cpuCores = 0,
  9. 9 _memorySize = 0,
  10. 10 _serverCost = 0,
  11. 11 _powerCost = 0;
  12. 12
  13. 13 for (int i = 0; i < server_info_stu->cpuCores.size() - 1; i++)
  14. 14 {
  15. 15 _cpuCores = 10 * _cpuCores + server_info_stu->cpuCores[i] - '0';
  16. 16 }
  17. 17
  18. 18 for (int i = 0; i < server_info_stu->memorySize.size() - 1; i++)
  19. 19 {
  20. 20 _memorySize = 10 * _memorySize + server_info_stu->memorySize[i] - '0';
  21. 21 }
  22. 22
  23. 23 for (int i = 0; i < server_info_stu->serverCost.size() - 1; i++)
  24. 24 {
  25. 25 _serverCost = 10 * _serverCost + server_info_stu->serverCost[i] - '0';
  26. 26 }
  27. 27
  28. 28 for (int i = 0; i < server_info_stu->powerCost.size() - 1; i++)
  29. 29 {
  30. 30 _powerCost = 10 * _powerCost + server_info_stu->powerCost[i] - '0';
  31. 31 }
  32. 32
  33. 33 serverInfos[_serverType] = vector<int>{ _cpuCores / 2 ,
  34. 34 _cpuCores / 2,
  35. 35 _memorySize / 2,
  36. 36 _memorySize / 2,
  37. 37 _serverCost,
  38. 38 _powerCost };
  39. 39 }
  1. 1 /* 解析txt文件时,将可售卖虚拟机类型信息解析保存
  2. 2 (型号,cpu核数,内存大小,是否双节点部署)
  3. 3 */
  4. 4 void generateVm(_vm_info_stu *vm_info_stu)
  5. 5 {
  6. 6 string _vmType;
  7. 7
  8. 8 for (int i = 1; i < vm_info_stu->vmType.size() - 1; i++) {
  9. 9 _vmType += vm_info_stu->vmType[i];
  10. 10 }
  11. 11
  12. 12 int _vmCpuCores = 0, _vmMemory = 0, _vmTwoNodes = 0;
  13. 13 for (int i = 0; i < vm_info_stu->vmCpuCores.size() - 1; i++) {
  14. 14 _vmCpuCores = _vmCpuCores * 10 + vm_info_stu->vmCpuCores[i] - '0';
  15. 15 }
  16. 16 for (int i = 0; i < vm_info_stu->vmMemory.size() - 1; i++) {
  17. 17 _vmMemory = _vmMemory * 10 + vm_info_stu->vmMemory[i] - '0';
  18. 18 }
  19. 19 if (vm_info_stu->vmTwoNodes[0] == '1') {
  20. 20 _vmTwoNodes = 1;
  21. 21 }
  22. 22 else {
  23. 23 _vmTwoNodes = 0;
  24. 24 }
  25. 25 vmInfos[_vmType] = vector<int>{ _vmCpuCores,
  26. 26 _vmMemory,
  27. 27 _vmTwoNodes };
  28. 28 }

  在读取文件时,采用freopen进行重定向到txt文件,采用cin标准输入读入服务器、虚拟机数据,并读人每天虚拟机请求。具体代码如下:

  1. 1 //在读取文件时,采用freopen进行重定向到txt文件,采用cin标准输入读取数据
  2. 2 #ifdef TEST
  3. 3 std::freopen(filePath.c_str(), "rb", stdin);
  4. 4 #endif
  5. 5 int serverNum;
  6. 6
  7. 7 scanf("%d", &serverNum);
  8. 8
  9. 9 for (int i = 0; i < serverNum; i++)
  10. 10 {
  11. 11 cin >> server_info_stu.serverType >> server_info_stu.cpuCores >> server_info_stu.memorySize >> server_info_stu.serverCost >> server_info_stu.powerCost;
  12. 12
  13. 13 generateServer(&server_info_stu);
  14. 14 }
  15. 15
  16. 16 int vmNumber = 0;
  17. 17 scanf("%d", &vmNumber);
  18. 18
  19. 19
  20. 20
  21. 21 for (int i = 0; i < vmNumber; i++) {
  22. 22 cin >> vm_info_stu.vmType >> vm_info_stu.vmCpuCores >> vm_info_stu.vmMemory >> vm_info_stu.vmTwoNodes;
  23. 23
  24. 24 generateVm(&vm_info_stu);
  25. 25
  26. 26 }
  27. 27
  28. 28 int requestdays = 0,
  29. 29 dayRequestNumber = 0;
  30. 30
  31. 31 scanf("%d", &requestdays);

3.3、服务器购买初始化

  服务器购买初始化非常重要,需要依据服务的性价比及分析前面天数的虚拟机CPU、MEM需求,来选择服务器,之后分单双节点分别实现,代码如下:

  1. 1 // 初始化server,如何初始化购买的服务器是一个大的优化
  2. 2 void Init_BuyServer()
  3. 3 {
  4. 4
  5. 5 string serverType;
  6. 6 bool flag = 0;
  7. 7
  8. 8 findVm_CM_max();
  9. 9 analyzeServerInfo();
  10. 10
  11. 11 for (int i = 0; i < 4000; i++)
  12. 12 {
  13. 13 NodeOnServerInfo[i] = vector<int>{ 0, 0 };
  14. 14 PreNodeOnServerInfo[i] = vector<int>{ 0, 0 };
  15. 15 }
  16. 16
  17. 17 for (auto it = vec.begin(); it != vec.end(); ++it)
  18. 18 {
  19. 19 if (flag == 0)
  20. 20 {
  21. 21 if (serverInfos[it->second][0] >= VM_max_Core && serverInfos[it->second][2] >= VM_max_Mem) //服务器内核和内存是最大虚拟需求的2倍,且性价比高
  22. 22 {
  23. 23 serverType = it->second;
  24. 24 flag = 1;
  25. 25 }
  26. 26 }
  27. 27 }
  28. 28
  29. 29 flag = 0;
  30. 30
  31. 31 //serverType = "hostUY41I"; hostTUL1P
  32. 32 //(hostTUL1P, 286, 858, 142387, 176)
  33. 33 serverType = "hostQ0Y9D";
  34. 34 int n = 700; //目前700最佳
  35. 35
  36. 36 int server_numberID = 0;
  37. 37
  38. 38 serverRunVms.resize(4000, 0);
  39. 39 string initBuy = "(purchase, ";
  40. 40 initBuy += to_string(2) + ")\n";
  41. 41
  42. 42 //vector<string> res;
  43. 43 res.push_back(initBuy); //(purchase, 2)
  44. 44
  45. 45 string pauseInfo = "(" + serverType + ", ";
  46. 46 pauseInfo += std::to_string(n / 2) + ")\n";
  47. 47
  48. 48 res.push_back(pauseInfo); //(hostUY41I, 1250)
  49. 49 day_BuyServers_res.push_back((serverType + std::to_string(0) + "," + std::to_string(n / 2)));
  50. 50 for (int i = 0; i < n / 2; i++)
  51. 51 {
  52. 52 //unordered_map<int,vector<int>> sysServerResource;
  53. 53 sysServerResource[serverNumber++] = serverInfos[serverType];
  54. 54 SERVERCOST += serverInfos[serverType][4];
  55. 55
  56. 56 //记录购买的虚拟机信息,为后面迁移做准备
  57. 57 purchase_service_info.purchase_service_ID_Info[server_numberID][0] = server_numberID; //存储服务器节点
  58. 58 purchase_service_info.purchase_service_nodeA_remainCPU[server_numberID] = serverInfos[serverType][0];
  59. 59 purchase_service_info.purchase_service_nodeB_remainCPU[server_numberID] = serverInfos[serverType][1];
  60. 60 purchase_service_info.purchase_service_nodeA_remainMEM[server_numberID] = serverInfos[serverType][2];
  61. 61 purchase_service_info.purchase_service_nodeB_remainMEM[server_numberID] = serverInfos[serverType][3];
  62. 62
  63. 63 // 1-->记录总的CPU 2->记录总的MEM
  64. 64 purchase_service_info.purchase_service_ID_Info[server_numberID][1] = serverInfos[serverType][0] + serverInfos[serverType][1];
  65. 65 purchase_service_info.purchase_service_ID_Info[server_numberID][2] = serverInfos[serverType][2] + serverInfos[serverType][3];
  66. 66
  67. 67 server_numberID++;
  68. 68
  69. 69 Total_Server_ID[serverNumber - 1] = string{ serverType + std::to_string(0) + "," + std::to_string(serverNumber - 1) };
  70. 70 }
  71. 71 //Total_Server_NameID[serverType] = int{ n / 2 - 1};
  72. 72 //ServerTypeBuyOrder[serverType] = int{ 1 };
  73. 73 //(host78BMY, 996, 332, 246869, 310)
  74. 74 //(hostUY41I, 676, 994, 243651, 305)
  75. 75 serverType = "hostC039T";
  76. 76 pauseInfo = "(" + serverType + ", ";
  77. 77 pauseInfo += std::to_string(serverNumber) + ")\n";//(host78BMY, 1250)
  78. 78
  79. 79 day_BuyServers_res.push_back((serverType + std::to_string(0) + "," + std::to_string(n / 2)));
  80. 80 res.push_back(pauseInfo);
  81. 81
  82. 82 for (int i = 0; i < n / 2; i++)
  83. 83 {
  84. 84 sysServerResource[serverNumber++] = serverInfos[serverType];
  85. 85 SERVERCOST += serverInfos[serverType][4];
  86. 86
  87. 87 //记录购买的虚拟机信息,为后面迁移做准备
  88. 88 purchase_service_info.purchase_service_ID_Info[server_numberID][0] = server_numberID; //存储服务器节点
  89. 89 purchase_service_info.purchase_service_nodeA_remainCPU[server_numberID] = serverInfos[serverType][0];
  90. 90 purchase_service_info.purchase_service_nodeB_remainCPU[server_numberID] = serverInfos[serverType][1];
  91. 91 purchase_service_info.purchase_service_nodeA_remainMEM[server_numberID] = serverInfos[serverType][2];
  92. 92 purchase_service_info.purchase_service_nodeB_remainMEM[server_numberID] = serverInfos[serverType][3];
  93. 93
  94. 94 // 1-->记录CPU 2->记录MEM
  95. 95 purchase_service_info.purchase_service_ID_Info[server_numberID][1] = serverInfos[serverType][0] + serverInfos[serverType][1];
  96. 96 purchase_service_info.purchase_service_ID_Info[server_numberID][2] = serverInfos[serverType][2] + serverInfos[serverType][3];
  97. 97
  98. 98
  99. 99 Total_Server_ID[serverNumber - 1] = string{ serverType + std::to_string(0) + "," + std::to_string(serverNumber - 1 - n / 2) };
  100. 100 }
  101. 101 //Total_Server_NameID[serverType] = int{ n / 2 - 1 };
  102. 102 //ServerTypeBuyOrder[serverType] = int{ 2 };
  103. 103 }

3.4、虚拟机迁移

  虚拟机迁移主要是利用了之前的结构体,结合虚拟机的add及del函数,对结构体参数进行处理,服务器迁移大策略就是编号末尾的服务器剩余CPU/MEM比较多的的迁移到前面服务器上去,尽量占满,为了减少服务器工作成本:

  1. 1 for (int _count = (purchase_service_info.purchased_Service_number - 1); _count >= 0; _count--)
  2. 2 {
  3. 3 //if (purchase_service_info.purchase_service_nodeA_remainCPU[_count] >= 0)
  4. 4 //{
  5. 5 float remain_cpu = (purchase_service_info.purchase_service_nodeA_remainCPU[_count]
  6. 6 + purchase_service_info.purchase_service_nodeB_remainCPU[_count])*1.0f
  7. 7 / purchase_service_info.purchase_service_ID_Info[_count][1] * 1.0f;
  8. 8
  9. 9 float remain_mem = (purchase_service_info.purchase_service_nodeA_remainMEM[_count]
  10. 10 + purchase_service_info.purchase_service_nodeB_remainMEM[_count])*1.0f
  11. 11 / purchase_service_info.purchase_service_ID_Info[_count][2] * 1.0f;
  12. 12
  13. 13 if ((remain_cpu > 0.8f) && (remain_cpu < 0.99f) && (remain_mem > 0.8f) && (remain_mem < 0.99f))
  14. 14 //if ((remain_cpu > 0.8f) && (remain_mem > 0.8f))
  15. 15 {
  16. 16 //for (int vm_tra = 3; purchase_service_info.purchase_service_ID_Info[_count][vm_tra] != 0; vm_tra= vm_tra+4)
  17. 17 for (int vm_tra = 3; vm_tra <= 239; vm_tra = vm_tra + 4) //30 -- 119 and 40 --159
  18. 18 {
  19. 19 if (purchase_service_info.purchase_service_ID_Info[_count][vm_tra] > 100)
  20. 20 {
  21. 21 for (int service_tra = 0; service_tra < 2600; service_tra++)
  22. 22 {
  23. 23 if (service_tra != _count) //服务器不能自己迁移到自己本身
  24. 24 {
  25. 25 //if (purchase_service_info.purchase_service_ID_Info[service_tra][vm_tra + 1]) //如果是双节点
  26. 26 if (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] == 1) //如果是双节点
  27. 27 {
  28. 28 if ((purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] >= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2))
  29. 29 && (purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] >= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2))
  30. 30 && (purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] >= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2))
  31. 31 && (purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] >= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2))
  32. 32 )
  33. 33 {
  34. 34 #ifdef My_PRINT
  35. 35 cout << "nodeA_remain cpu:" << purchase_service_info.purchase_service_nodeA_remainCPU[_count] << " 1 " << purchase_service_info.purchase_service_ID_Info[_count][1] << endl;
  36. 36 cout << "nodeB_remain cpu:" << purchase_service_info.purchase_service_nodeB_remainCPU[_count] << " 1 " << purchase_service_info.purchase_service_ID_Info[_count][1] << endl;
  37. 37 cout << "nodeA_remain mem:" << purchase_service_info.purchase_service_nodeA_remainMEM[_count] << " 1 " << purchase_service_info.purchase_service_ID_Info[_count][2] << endl;
  38. 38 cout << "nodeB_remain mem:" << purchase_service_info.purchase_service_nodeB_remainMEM[_count] << " 1 " << purchase_service_info.purchase_service_ID_Info[_count][2] << endl;
  39. 39 #endif
  40. 40
  41. 41 purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] -= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2);
  42. 42 purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] -= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2);
  43. 43 purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] -= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2);
  44. 44 purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] -= (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2);
  45. 45
  46. 46 //需要补充选定服务器移出去的虚拟机的CPU和MEM
  47. 47 purchase_service_info.purchase_service_nodeA_remainCPU[_count] += (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2);
  48. 48 purchase_service_info.purchase_service_nodeB_remainCPU[_count] += (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] / 2);
  49. 49 purchase_service_info.purchase_service_nodeA_remainMEM[_count] += (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2);
  50. 50 purchase_service_info.purchase_service_nodeB_remainMEM[_count] += (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] / 2);
  51. 51
  52. 52 #ifdef My_PRINT
  53. 53 cout << "nodeA_remain cpu:" << purchase_service_info.purchase_service_nodeA_remainCPU[_count] << " 2 " << purchase_service_info.purchase_service_ID_Info[_count][1] << endl;
  54. 54 cout << "nodeB_remain cpu:" << purchase_service_info.purchase_service_nodeB_remainCPU[_count] << " 2 " << purchase_service_info.purchase_service_ID_Info[_count][1] << endl;
  55. 55 cout << "nodeA_remain mem:" << purchase_service_info.purchase_service_nodeA_remainMEM[_count] << " 2 " << purchase_service_info.purchase_service_ID_Info[_count][2] << endl;
  56. 56 cout << "nodeB_remain mem:" << purchase_service_info.purchase_service_nodeB_remainMEM[_count] << " 2 " << purchase_service_info.purchase_service_ID_Info[_count][2] << endl;
  57. 57 #endif
  58. 58
  59. 59 //vmOnServer[vmId] = vector<int>{ serverId,vmCores,vmMemory,1,2 };
  60. 60
  61. 61 vmOnServer[std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra])] = vector<int>{
  62. 62 purchase_service_info.purchase_service_ID_Info[service_tra][0],
  63. 63 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2],
  64. 64 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3],1,2 };
  65. 65
  66. 66
  67. 67
  68. 68 assert(purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] >= 0
  69. 69 && purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] >= 0
  70. 70 && purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] >= 0
  71. 71 && purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] >= 0);
  72. 72
  73. 73
  74. 74 assert((purchase_service_info.purchase_service_ID_Info[_count][1] / 2) >= purchase_service_info.purchase_service_nodeA_remainCPU[_count]
  75. 75 && (purchase_service_info.purchase_service_ID_Info[_count][1] / 2) >= purchase_service_info.purchase_service_nodeB_remainCPU[_count]
  76. 76 && (purchase_service_info.purchase_service_ID_Info[_count][2] / 2) >= purchase_service_info.purchase_service_nodeA_remainMEM[_count]
  77. 77 && (purchase_service_info.purchase_service_ID_Info[_count][2] / 2) >= purchase_service_info.purchase_service_nodeB_remainMEM[_count]);
  78. 78
  79. 79 string s;
  80. 80 string _migration = "migration";
  81. 81 s = "(" + _migration + ", ";
  82. 82 s += std::to_string(1) + ")\n";//(migration, count_migration)
  83. 83 res.push_back(s);
  84. 84 #ifdef My_PRINT
  85. 85 cout << s << endl;
  86. 86 #endif
  87. 87
  88. 88 s = "(" + std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra]) + ", ";
  89. 89 s += std::to_string(purchase_service_info.purchase_service_ID_Info[service_tra][0]) + ")\n";//(虚拟机ID, 目的服务器ID)*/
  90. 90
  91. 91 res.push_back(s);
  92. 92
  93. 93 //添加移入服务器上虚拟机的信息
  94. 94 for (int load_vm = 0; load_vm < 60; load_vm++) //因为del的原因,需要解决删除信息的方面
  95. 95 {
  96. 96 if (purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] == 0)
  97. 97 {
  98. 98 purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra];
  99. 99 purchase_service_info.purchase_service_ID_Info[service_tra][4 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1]; //Nodes
  100. 100 purchase_service_info.purchase_service_ID_Info[service_tra][5 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2]; //CPU
  101. 101 purchase_service_info.purchase_service_ID_Info[service_tra][6 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3]; //MEM
  102. 102
  103. 103 break;
  104. 104 }
  105. 105
  106. 106
  107. 107 }
  108. 108
  109. 109 //需要删除从服务器移走虚拟机的信息
  110. 110 purchase_service_info.purchase_service_ID_Info[_count][vm_tra] = 0;
  111. 111 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] = 0; //Nodes
  112. 112 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] = 0; //CPU
  113. 113 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] = 0; //MEM
  114. 114
  115. 115 #ifdef My_PRINT
  116. 116 cout << s << endl;
  117. 117 #endif
  118. 118
  119. 119 //计算功耗需要 扣除服务器的虚拟机数量
  120. 120 serverRunVms[_count]--;
  121. 121 serverRunVms[service_tra]++;
  122. 122
  123. 123
  124. 124 count_migration--;
  125. 125
  126. 126 //break; //如果判断是可以移植的话,即进行移植,移植完之后 立马进行下一个虚拟机
  127. 127 return 0;
  128. 128 }
  129. 129 else
  130. 130 {
  131. 131 //否则判断下一个服务器 CPU和MEM(从小号往大号)
  132. 132 }
  133. 133 }
  134. 134 else if (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] == 2)//需要对A节点点进行选择移植 不需要除/2
  135. 135 {
  136. 136 if ((purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] >= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2])
  137. 137 && (purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] >= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3]))
  138. 138 {
  139. 139
  140. 140 purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] -= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2];
  141. 141 purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] -= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3];
  142. 142
  143. 143 //需要补充选定服务器移出去的虚拟机的CPU和MEM
  144. 144 purchase_service_info.purchase_service_nodeA_remainCPU[_count] += purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2];
  145. 145 purchase_service_info.purchase_service_nodeA_remainMEM[_count] += purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3];
  146. 146
  147. 147
  148. 148 vmOnServer[std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra])] = vector<int>{
  149. 149 purchase_service_info.purchase_service_ID_Info[service_tra][0],
  150. 150 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2],
  151. 151 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3],1 };
  152. 152
  153. 153
  154. 154 assert(purchase_service_info.purchase_service_nodeA_remainCPU[service_tra] >= 0
  155. 155 && purchase_service_info.purchase_service_nodeA_remainMEM[service_tra] >= 0);
  156. 156
  157. 157
  158. 158 assert(purchase_service_info.purchase_service_ID_Info[_count][1] / 2 >= purchase_service_info.purchase_service_nodeA_remainCPU[_count]
  159. 159 && purchase_service_info.purchase_service_ID_Info[_count][2] / 2 >= purchase_service_info.purchase_service_nodeA_remainMEM[_count]);
  160. 160
  161. 161 string s;
  162. 162 string _migration = "migration";
  163. 163 s = "(" + _migration + ", ";
  164. 164 s += std::to_string(1) + ")\n";//(migration, count_migration)
  165. 165 res.push_back(s);
  166. 166 #ifdef My_PRINT
  167. 167 cout << s << endl;
  168. 168 #endif
  169. 169
  170. 170 s = "(" + std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra]) + ", ";
  171. 171 string _AA_A = "A";
  172. 172 s += std::to_string(purchase_service_info.purchase_service_ID_Info[service_tra][0]) + ", ";//(虚拟机ID, 目的服务器ID, A)
  173. 173 s += _AA_A + ")\n";
  174. 174 res.push_back(s);
  175. 175
  176. 176 //添加移入服务器上虚拟机的信息
  177. 177 for (int load_vm = 0; load_vm < 60; load_vm++) //因为del的原因,需要解决删除信息的方面
  178. 178 {
  179. 179 if (purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] == 0)
  180. 180 {
  181. 181 purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra];
  182. 182 purchase_service_info.purchase_service_ID_Info[service_tra][4 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1]; //Nodes
  183. 183 purchase_service_info.purchase_service_ID_Info[service_tra][5 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2]; //CPU
  184. 184 purchase_service_info.purchase_service_ID_Info[service_tra][6 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3]; //MEM
  185. 185
  186. 186 break;
  187. 187 }
  188. 188
  189. 189
  190. 190 }
  191. 191
  192. 192 //需要删除从服务器移走虚拟机的信息
  193. 193 purchase_service_info.purchase_service_ID_Info[_count][vm_tra] = 0;
  194. 194 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] = 0; //Nodes
  195. 195 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] = 0; //CPU
  196. 196 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] = 0; //MEM
  197. 197 #ifdef My_PRINT
  198. 198 cout << s << endl;
  199. 199 #endif
  200. 200
  201. 201 //计算功耗需要 扣除服务器的虚拟机数量
  202. 202 serverRunVms[_count]--;
  203. 203 serverRunVms[service_tra]++;
  204. 204
  205. 205
  206. 206 count_migration--;
  207. 207
  208. 208 //break; //如果判断是可以移植的话,即进行移植,移植完之后 立马进行下一个虚拟机
  209. 209 return 0;
  210. 210 }
  211. 211 else
  212. 212 {
  213. 213 ;
  214. 214 }
  215. 215 }
  216. 216 else if (purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] == 3)//需要对B节点点进行选择移植 不需要除/2
  217. 217 {
  218. 218 if ((purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] >= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2])
  219. 219 && (purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] >= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3]))
  220. 220 {
  221. 221
  222. 222
  223. 223 purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] -= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2];
  224. 224 purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] -= purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3];
  225. 225
  226. 226 #ifdef TEST
  227. 227 cout << purchase_service_info.purchase_service_nodeB_remainCPU[_count] << purchase_service_info.purchase_service_ID_Info[_count][1] << endl;
  228. 228 #endif
  229. 229 //需要补充选定服务器移出去的虚拟机的CPU和MEM
  230. 230 purchase_service_info.purchase_service_nodeB_remainCPU[_count] += purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2];
  231. 231 purchase_service_info.purchase_service_nodeB_remainMEM[_count] += purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3];
  232. 232
  233. 233
  234. 234 vmOnServer[std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra])] = vector<int>{
  235. 235 purchase_service_info.purchase_service_ID_Info[service_tra][0],
  236. 236 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2],
  237. 237 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3],2 };
  238. 238
  239. 239
  240. 240 #ifdef TEST
  241. 241 cout << purchase_service_info.purchase_service_nodeB_remainCPU[_count] << endl;
  242. 242 #endif
  243. 243
  244. 244 assert(purchase_service_info.purchase_service_nodeB_remainCPU[service_tra] >= 0
  245. 245 && purchase_service_info.purchase_service_nodeB_remainMEM[service_tra] >= 0);
  246. 246
  247. 247
  248. 248 assert(purchase_service_info.purchase_service_ID_Info[_count][1] / 2 >= purchase_service_info.purchase_service_nodeB_remainCPU[_count]
  249. 249 && purchase_service_info.purchase_service_ID_Info[_count][2] / 2 >= purchase_service_info.purchase_service_nodeB_remainMEM[_count]);
  250. 250
  251. 251 string s;
  252. 252 string _migration = "migration";
  253. 253 s = "(" + _migration + ", ";
  254. 254 s += std::to_string(1) + ")\n";//(migration, count_migration)
  255. 255 res.push_back(s);
  256. 256 #ifdef My_PRINT
  257. 257 cout << s << endl;
  258. 258 #endif
  259. 259
  260. 260 s = "(" + std::to_string(purchase_service_info.purchase_service_ID_Info[_count][vm_tra]) + ", ";
  261. 261 string _BB_B = "B";
  262. 262 s += std::to_string(purchase_service_info.purchase_service_ID_Info[service_tra][0]) + ", ";//(虚拟机ID, 目的服务器ID, B)
  263. 263 s += _BB_B + ")\n";
  264. 264 res.push_back(s);
  265. 265
  266. 266 //添加移入服务器上虚拟机的信息
  267. 267 for (int load_vm = 0; load_vm < 60; load_vm++) //因为del的原因,需要解决删除信息的方面
  268. 268 {
  269. 269 if (purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] == 0)
  270. 270 {
  271. 271 purchase_service_info.purchase_service_ID_Info[service_tra][3 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra];
  272. 272 purchase_service_info.purchase_service_ID_Info[service_tra][4 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1]; //Nodes
  273. 273 purchase_service_info.purchase_service_ID_Info[service_tra][5 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2]; //CPU
  274. 274 purchase_service_info.purchase_service_ID_Info[service_tra][6 + 4 * load_vm] = purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3]; //MEM
  275. 275
  276. 276 break;
  277. 277 }
  278. 278
  279. 279
  280. 280 }
  281. 281
  282. 282 //需要删除从服务器移走虚拟机的信息
  283. 283 purchase_service_info.purchase_service_ID_Info[_count][vm_tra] = 0;
  284. 284 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 1] = 0; //Nodes
  285. 285 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 2] = 0; //CPU
  286. 286 purchase_service_info.purchase_service_ID_Info[_count][vm_tra + 3] = 0; //MEM
  287. 287
  288. 288
  289. 289 #ifdef My_PRINT
  290. 290 cout << s << endl;
  291. 291 #endif
  292. 292
  293. 293 //计算功耗需要 扣除服务器的虚拟机数量
  294. 294 serverRunVms[_count]--;
  295. 295 serverRunVms[service_tra]++;
  296. 296
  297. 297
  298. 298 count_migration--;
  299. 299
  300. 300 //break; //如果判断是可以移植的话,即进行移植,移植完之后 立马进行下一个虚拟机
  301. 301 return 0;
  302. 302 }
  303. 303 else
  304. 304 {
  305. 305 ;
  306. 306 }
  307. 307 }
  308. 308
  309. 309 if (count_migration == 0)
  310. 310 {
  311. 311 return 0;
  312. 312 }
  313. 313 }
  314. 314 else
  315. 315 {
  316. 316 ;
  317. 317 }
  318. 318 }
  319. 319 }
  320. 320 else
  321. 321 {
  322. 322 ;
  323. 323 }
  324. 324 }
  325. 325 //不移动
  326. 326 /*
  327. 327 if (no_shift == 1)
  328. 328 {
  329. 329 string s = "(migration, 0)\n";
  330. 330 res.push_back(s);
  331. 331
  332. 332 no_shift = 0;
  333. 333 }
  334. 334 */
  335. 335
  336. 336 }
  337. 337 else
  338. 338 {
  339. 339 //否则判断上一个服务器 CPU和MEM(从大号往小号)
  340. 340 }
  341. 341
  342. 342 if (count_migration == 0)
  343. 343 {
  344. 344 return 0;
  345. 345 }
  346. 346 //}
  347. 347 }
View Code

3.4、后期优化方向  

  如何初始化购买服务器,如何进行虚拟机的迁移,还有扩容策略是优化的重要方面,可能这是个NP-Hard问题。我在这版代码下,只是实现了虚拟机迁移的一大点,初始化购买服务器和扩容策略是由师兄一起讨论,从最后结果来看,我迁移的算法层面还是欠缺,没有做好程序的高效移植性,c++功底还是偏弱,和师兄的讨论还是少了,对任务的分配还是没有非常明确,个人对工程算法实现层面弱,Debug能力弱,希望后面多多学习。

原文链接:http://www.cnblogs.com/iFrank/p/14587524.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号