|
- /*
-
- Copyright (c) [2023] [pcm]
- [pcm-coordinator] is licensed under Mulan PSL v2.
- You can use this software according to the terms and conditions of the Mulan PSL v2.
- You may obtain a copy of Mulan PSL v2 at:
- http://license.coscl.org.cn/MulanPSL2
- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
- EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
- See the Mulan PSL v2 for more details.
-
- */
-
- package strategy
-
- import (
- "errors"
- "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/algorithm/providerPricing"
- "gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/strategy/param"
- "strconv"
- )
-
- type PricingStrategy struct {
- ProviderList []*providerPricing.Provider
- Task *providerPricing.Task
- StrategyList []*providerPricing.Strategy
- }
-
- func NewPricingStrategy(params *param.ResourcePricingParams) *PricingStrategy {
- providers := params.GetProviders()
- task := params.GetTask()
- var providerList []*providerPricing.Provider
- var res [][]int
-
- for _, p := range providers {
- p.GenMaxResourceNum(task)
- providerList = append(providerList, p)
- }
-
- providerPricing.Back_trace_task(task.Replicas, 0, providerList, 0, &res, 0)
-
- var strategyList []*providerPricing.Strategy
- for _, r := range res {
- var path []int
- var pathlist [][]int
-
- var resourcePerProvider []int
- for j, p := range providerList {
- if r[j] > p.MaxReplicas {
- resourcePerProvider = append(resourcePerProvider, p.MaxReplicas)
- } else {
- resourcePerProvider = append(resourcePerProvider, r[j])
- }
- }
- providerPricing.Back_trace_resource(resourcePerProvider, 0, path, &pathlist)
- strategy := providerPricing.NewStrategy()
- strategy.Tasksolution = r
- strategy.Resourcesolution = pathlist
- strategyList = append(strategyList, strategy)
- }
-
- return &PricingStrategy{ProviderList: providerList, Task: task, StrategyList: strategyList}
- }
-
- func (ps *PricingStrategy) computeMaxScore() (*providerPricing.Task, error) {
- maxStrategy := providerPricing.NewStrategy()
- var maxprofit float64
-
- //先计算出最大的利润值
- for _, strategy := range ps.StrategyList {
- for _, resourceSolu := range strategy.Resourcesolution {
- profit := providerPricing.ComputeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
- if profit > maxprofit {
- maxprofit = profit
- }
- }
- }
-
- for _, strategy := range ps.StrategyList {
- for _, resourceSolu := range strategy.Resourcesolution {
- profit := providerPricing.ComputeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
- highDegree := providerPricing.ComputeHighDegree(ps.Task, resourceSolu, ps.ProviderList)
-
- valueSum := profit/maxprofit + highDegree
-
- //将每个确定任务分配策略的最高的策略得分存储到里面
- if valueSum > maxStrategy.ValueSum {
- strategy.Profit = profit
- strategy.HighDegree = highDegree
- }
-
- if valueSum > maxStrategy.ValueSum {
- maxStrategy.ValueSum = valueSum
- maxStrategy.Tasksolution = strategy.Tasksolution
- newResourceSolu := [][]int{}
- newResourceSolu = append(newResourceSolu, resourceSolu)
- maxStrategy.Resourcesolution = newResourceSolu
- maxStrategy.Profit = profit
- maxStrategy.HighDegree = highDegree
- }
- }
- }
-
- if len(ps.ProviderList) == 0 {
- return nil, errors.New("empty providers")
- }
-
- ps.Task.MaxscoreStrategy = maxStrategy // 记录该任务的最终分配策略
- return ps.Task, nil
- }
-
- func (ps *PricingStrategy) produceMaxScoreStrategy() (*providerPricing.Strategy, error) {
- task, err := ps.computeMaxScore()
- if err != nil {
- return nil, err
- }
-
- //计算任务i的resourcePerTask属性
- for i, _ := range ps.ProviderList {
- tasksolu := task.MaxscoreStrategy.Tasksolution[i] // 第j个提供商分到的任务数
- resourcesolu := task.MaxscoreStrategy.Resourcesolution[0][i] // 第j个提供商分到的资源数
-
- // 在第j个云提供商处声明一个长度为资源数的链表
- resourcePerTaskPerProviders := make([]int, resourcesolu)
- if tasksolu > 0 {
- for tasksolu > 0 {
- for j := 0; j < resourcesolu; j++ {
- resourcePerTaskPerProviders[j] += 1
- tasksolu -= 1
- }
- }
- } else if tasksolu == 0 {
- resourcePerTaskPerProviders = []int{0}
- }
-
- task.ResourcePerTask = append(task.ResourcePerTask, resourcePerTaskPerProviders)
- }
-
- return task.MaxscoreStrategy, nil
- }
-
- func (ps *PricingStrategy) Schedule() ([]*AssignedCluster, error) {
- strategy, err := ps.produceMaxScoreStrategy()
- if err != nil {
- return nil, err
- }
-
- if len(strategy.Tasksolution) == 0 {
- return nil, errors.New("调度失败, 未能获取调度结果")
- }
-
- var results []*AssignedCluster
- for i, e := range strategy.Tasksolution {
- if e == 0 {
- continue
- }
- cluster := &AssignedCluster{ClusterId: strconv.FormatInt(ps.ProviderList[i].Pid, 10), Replicas: int32(e)}
- results = append(results, cluster)
- }
-
- if len(results) == 0 {
- return nil, errors.New("可用集群为空")
- }
-
- return results, nil
- }
|