You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

k8sStrategy.go 7.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package algo
  2. import (
  3. "errors"
  4. "gonum.org/v1/gonum/mat"
  5. "math"
  6. )
  7. type k8sStrategy struct {
  8. ProviderList []*Provider
  9. Task *Task
  10. StrategyList []*Strategy
  11. }
  12. func NewK8sStrategy(task *Task, providers ...*Provider) *k8sStrategy {
  13. var providerList []*Provider
  14. var res [][]int
  15. for _, p := range providers {
  16. p.GenMaxResourceNum(task)
  17. providerList = append(providerList, p)
  18. }
  19. back_trace_task(task.Replicas, 0, providerList, 0, &res, 0)
  20. var strategyList []*Strategy
  21. for _, r := range res {
  22. var path []int
  23. var pathlist [][]int
  24. var resourcePerProvider []int
  25. for j, p := range providerList {
  26. if r[j] > p.MaxReplicas {
  27. resourcePerProvider = append(resourcePerProvider, p.MaxReplicas)
  28. } else {
  29. resourcePerProvider = append(resourcePerProvider, r[j])
  30. }
  31. }
  32. back_trace_resource(resourcePerProvider, 0, path, &pathlist)
  33. strategy := NewStrategy()
  34. strategy.Tasksolution = r
  35. strategy.Resourcesolution = pathlist
  36. strategyList = append(strategyList, strategy)
  37. }
  38. return &k8sStrategy{ProviderList: providerList, Task: task, StrategyList: strategyList}
  39. }
  40. func (ps k8sStrategy) computeMaxScore() (*Task, error) {
  41. maxStrategy := NewStrategy()
  42. var maxprofit float64
  43. //先计算出最大的利润值
  44. for _, strategy := range ps.StrategyList {
  45. for _, resourceSolu := range strategy.Resourcesolution {
  46. profit := computeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
  47. if profit > maxprofit {
  48. maxprofit = profit
  49. }
  50. }
  51. }
  52. for _, strategy := range ps.StrategyList {
  53. for _, resourceSolu := range strategy.Resourcesolution {
  54. profit := computeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
  55. highDegree := computeHighDegree(ps.Task, resourceSolu, ps.ProviderList)
  56. valueSum := profit/maxprofit + highDegree
  57. //将每个确定任务分配策略的最高的策略得分存储到里面
  58. if valueSum > maxStrategy.ValueSum {
  59. strategy.Profit = profit
  60. strategy.HighDegree = highDegree
  61. }
  62. if valueSum > maxStrategy.ValueSum {
  63. maxStrategy.ValueSum = valueSum
  64. maxStrategy.Tasksolution = strategy.Tasksolution
  65. newResourceSolu := [][]int{}
  66. newResourceSolu = append(newResourceSolu, resourceSolu)
  67. maxStrategy.Resourcesolution = newResourceSolu
  68. maxStrategy.Profit = profit
  69. maxStrategy.HighDegree = highDegree
  70. }
  71. }
  72. }
  73. if len(ps.ProviderList) == 0 {
  74. return nil, errors.New("empty providers")
  75. }
  76. ps.Task.MaxscoreStrategy = maxStrategy // 记录该任务的最终分配策略
  77. return ps.Task, nil
  78. }
  79. func computeProfit(task *Task, tasksolution []int, resourcesolution []int, providerList []*Provider) float64 {
  80. var timeexecution int //记录任务的实际最大执行时间
  81. var costSum float64 //该任务在多个云厂商所需支付的成本总价
  82. for i, provider := range providerList {
  83. //如果该厂商分的任务为0,则直接跳过该厂商,循环到下一厂商
  84. if tasksolution[i] == 0 {
  85. continue
  86. }
  87. //先计算下该云厂商的执行时间ddl,并替换任务的最大执行时间,向上取整
  88. t := math.Ceil(float64(tasksolution[i])/float64(resourcesolution[i])) * float64(task.Time)
  89. if int(t) > timeexecution {
  90. timeexecution = int(t)
  91. }
  92. //计算前几份资源多执行任务
  93. forOneMoreTaskNUm := tasksolution[i] % resourcesolution[i]
  94. for j := 0; j < resourcesolution[i]; j++ {
  95. if j < forOneMoreTaskNUm {
  96. t = math.Ceil(float64(tasksolution[i])/float64(resourcesolution[i])) * float64(task.Time)
  97. } else {
  98. t = math.Floor(float64(tasksolution[i])/float64(resourcesolution[i])) * float64(task.Time)
  99. }
  100. //如果这份资源分的的任务数
  101. cost := (provider.CpuCost*task.Cpu + provider.MemCost*task.Mem + provider.DiskCost*task.Disk) * t * (math.Pow(float64(j+1), math.Log2(provider.LearnIndex)))
  102. costSum += cost
  103. }
  104. }
  105. //计算用户的支付价格pay
  106. pay := task.Pr
  107. if timeexecution == task.Time { //没有排队等待,且只有一个副本直接执行或者多个副本完全并行执行
  108. if pay < costSum {
  109. pay = costSum
  110. }
  111. } else if timeexecution >= task.T0 && timeexecution <= task.T1 { //有排队时间或者任务存在串行执行
  112. if task.T1 == task.T0 { //仅有一个副本,时间中有排队时间
  113. e := math.Exp(float64(-task.B) * float64(timeexecution-task.T1))
  114. pay = (1 - 1/(1+e)) * task.Pr
  115. } else { //多个副本
  116. e := math.Exp(float64(-task.B) * float64(timeexecution-task.T1) / float64(task.T1-task.T0))
  117. pay = (1 - 1/(1+e)) * task.Pr
  118. }
  119. if pay < costSum {
  120. pay = costSum
  121. }
  122. } else { //超出用户满意度的完全串行时间
  123. pay = 1 / 2 * task.Pr
  124. if pay < costSum {
  125. pay = costSum
  126. }
  127. }
  128. profitSum := pay - costSum
  129. return profitSum
  130. }
  131. func computeHighDegree(task *Task, resourcesolution []int, providerList []*Provider) float64 {
  132. var highDegreeSum float64
  133. // 依次计算每个云厂商的资源可用度
  134. for i, provider := range providerList {
  135. // 定义两个四维向量
  136. // 未来任务资源需求比例
  137. futureDemand := mat.NewVecDense(3, []float64{1, 1, 1})
  138. // 定义假设按此方案分配后的剩余资源可用量,时间虽然有差异,但是先按那个时刻算吧,这里可能还要改一下
  139. nowLeft_cpu := provider.CpuAvail - task.Cpu*float64(resourcesolution[i])
  140. nowLeft_mem := provider.MemAvail - task.Mem*float64(resourcesolution[i])
  141. nowLeft_disk := provider.DiskAvail - task.Disk*float64(resourcesolution[i])
  142. nowLeft := mat.NewVecDense(3, []float64{nowLeft_cpu, nowLeft_mem, nowLeft_disk})
  143. // 使用余弦相似度计算两个比值的相近度
  144. // 计算向量的内积
  145. dot_product := mat.Dot(futureDemand, nowLeft)
  146. // 计算向量的模长
  147. magnitude1 := mat.Norm(futureDemand, 2)
  148. magnitude2 := mat.Norm(nowLeft, 2)
  149. // 计算余弦相似度
  150. cosine_similarity := dot_product / (magnitude1 * magnitude2)
  151. highDegreeSum += cosine_similarity
  152. }
  153. return highDegreeSum / float64(len(providerList))
  154. }
  155. func back_trace_task(ReplicaNum int, DoneReplicasNum int, providerList []*Provider, staclu int, res *[][]int, sum int) {
  156. //var count int = 0
  157. pnum := len(providerList)
  158. //所有的任务数都已经进行分配
  159. if DoneReplicasNum == ReplicaNum {
  160. var a []int
  161. for i := 0; i < pnum; i++ {
  162. a = append(a, providerList[i].CurReplicas)
  163. }
  164. *res = append(*res, a)
  165. //(*res)[0] = append((*res)[0], a)
  166. //count += 1
  167. return
  168. }
  169. //遍历完所有的云厂商序号
  170. if staclu >= pnum {
  171. return
  172. }
  173. if providerList[staclu].CurReplicas < providerList[staclu].MaxTaskCanRun {
  174. providerList[staclu].CurReplicas += 1
  175. back_trace_task(ReplicaNum, DoneReplicasNum+1, providerList, staclu, res, sum)
  176. providerList[staclu].CurReplicas -= 1
  177. back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
  178. } else {
  179. back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
  180. }
  181. }
  182. func back_trace_resource(list []int, i int, path []int, pathlist *[][]int) {
  183. if i == len(list) {
  184. var pathCopy = make([]int, len(path))
  185. copy(pathCopy, path)
  186. *pathlist = append(*pathlist, pathCopy)
  187. return
  188. }
  189. if list[i] == 0 {
  190. path = append(path, 0)
  191. back_trace_resource(list, i+1, path, pathlist)
  192. path = path[:len(path)-1]
  193. } else {
  194. for j := 1; j < list[i]+1; j++ {
  195. path = append(path, j)
  196. back_trace_resource(list, i+1, path, pathlist)
  197. path = path[:len(path)-1]
  198. }
  199. }
  200. }

PCM is positioned as Software stack over Cloud, aiming to build the standards and ecology of heterogeneous cloud collaboration for JCC in a non intrusive and autonomous peer-to-peer manner.