Merge pull request 'Refactor scheduler structure' (#2) from tzwang/pcm-coordinator:scheduler_restruct into master

This commit is contained in:
tzwang 2024-01-11 16:15:37 +08:00
commit e0fe198f66
11 changed files with 184 additions and 177 deletions

View File

@ -17,7 +17,7 @@ package scheduler
import (
"gitlink.org.cn/jcce-pcm/pcm-coordinator/api/pkg/response"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/models"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algo"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/utils"
"gorm.io/gorm"
)
@ -41,22 +41,22 @@ func (as *aiScheduler) getNewStructForDb(task *response.TaskInfo, resource strin
return ai, nil
}
func (as *aiScheduler) pickOptimalStrategy(task *algo.Task, providers ...*algo.Provider) (*algo.Strategy, error) {
func (as *aiScheduler) pickOptimalStrategy(task *providerPricing.Task, providers ...*providerPricing.Provider) (*providerPricing.Strategy, error) {
return nil, nil
}
func (as *aiScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*algo.Task, []*algo.Provider) {
func (as *aiScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*providerPricing.Task, []*providerPricing.Provider) {
var proParams []providerParams
sqlstr := "SELECT SUM(a.disk_avail) as disk_avail,SUM(a.mem_avail) as mem_avail,SUM(a.cpu_total * a.cpu_usable) as cpu_avail,participant_id from (SELECT * from sc_node_avail_info where created_time in (SELECT MAX(created_time) as time from sc_node_avail_info where deleted_flag = 0 GROUP BY participant_id,node_name)) a GROUP BY a.participant_id"
dbEngin.Raw(sqlstr).Scan(&proParams)
var providerList []*algo.Provider
var providerList []*providerPricing.Provider
for _, p := range proParams {
provider := algo.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
provider := providerPricing.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
providerList = append(providerList, provider)
}
t := algo.NewTask(0, 1, 2, 75120000, 301214500, 1200, 2, 6, 2000)
t := providerPricing.NewTask(0, 1, 2, 75120000, 301214500, 1200, 2, 6, 2000)
return t, providerList
}

View File

@ -1,49 +0,0 @@
/*
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 algo
type strategyService interface {
computeMaxScore() (*Task, error)
}
func ScheduleWithFullCollaboration(strategyService strategyService, ProviderList []*Provider) (*Task, error) {
task, err := strategyService.computeMaxScore()
if err != nil {
return nil, err
}
//计算任务i的resourcePerTask属性
for i, _ := range 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, nil
}

View File

@ -12,102 +12,14 @@
*/
package algo
package providerPricing
import (
"errors"
"gonum.org/v1/gonum/mat"
"math"
)
type k8sStrategy struct {
ProviderList []*Provider
Task *Task
StrategyList []*Strategy
}
func NewK8sStrategy(task *Task, providers ...*Provider) *k8sStrategy {
var providerList []*Provider
var res [][]int
for _, p := range providers {
p.GenMaxResourceNum(task)
providerList = append(providerList, p)
}
back_trace_task(task.Replicas, 0, providerList, 0, &res, 0)
var strategyList []*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])
}
}
back_trace_resource(resourcePerProvider, 0, path, &pathlist)
strategy := NewStrategy()
strategy.Tasksolution = r
strategy.Resourcesolution = pathlist
strategyList = append(strategyList, strategy)
}
return &k8sStrategy{ProviderList: providerList, Task: task, StrategyList: strategyList}
}
func (ps *k8sStrategy) computeMaxScore() (*Task, error) {
maxStrategy := NewStrategy()
var maxprofit float64
//先计算出最大的利润值
for _, strategy := range ps.StrategyList {
for _, resourceSolu := range strategy.Resourcesolution {
profit := computeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
if profit > maxprofit {
maxprofit = profit
}
}
}
for _, strategy := range ps.StrategyList {
for _, resourceSolu := range strategy.Resourcesolution {
profit := computeProfit(ps.Task, strategy.Tasksolution, resourceSolu, ps.ProviderList)
highDegree := 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 computeProfit(task *Task, tasksolution []int, resourcesolution []int, providerList []*Provider) float64 {
func ComputeProfit(task *Task, tasksolution []int, resourcesolution []int, providerList []*Provider) float64 {
var timeexecution int //记录任务的实际最大执行时间
var costSum float64 //该任务在多个云厂商所需支付的成本总价
@ -170,7 +82,7 @@ func computeProfit(task *Task, tasksolution []int, resourcesolution []int, provi
return profitSum
}
func computeHighDegree(task *Task, resourcesolution []int, providerList []*Provider) float64 {
func ComputeHighDegree(task *Task, resourcesolution []int, providerList []*Provider) float64 {
var highDegreeSum float64
// 依次计算每个云厂商的资源可用度
for i, provider := range providerList {
@ -205,7 +117,7 @@ func computeHighDegree(task *Task, resourcesolution []int, providerList []*Provi
return highDegreeSum / float64(len(providerList))
}
func back_trace_task(ReplicaNum int, DoneReplicasNum int, providerList []*Provider, staclu int, res *[][]int, sum int) {
func Back_trace_task(ReplicaNum int, DoneReplicasNum int, providerList []*Provider, staclu int, res *[][]int, sum int) {
//var count int = 0
pnum := len(providerList)
@ -228,16 +140,16 @@ func back_trace_task(ReplicaNum int, DoneReplicasNum int, providerList []*Provid
if providerList[staclu].CurReplicas < providerList[staclu].MaxTaskCanRun {
providerList[staclu].CurReplicas += 1
back_trace_task(ReplicaNum, DoneReplicasNum+1, providerList, staclu, res, sum)
Back_trace_task(ReplicaNum, DoneReplicasNum+1, providerList, staclu, res, sum)
providerList[staclu].CurReplicas -= 1
back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
Back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
} else {
back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
Back_trace_task(ReplicaNum, DoneReplicasNum, providerList, staclu+1, res, sum)
}
}
func back_trace_resource(list []int, i int, path []int, pathlist *[][]int) {
func Back_trace_resource(list []int, i int, path []int, pathlist *[][]int) {
if i == len(list) {
var pathCopy = make([]int, len(path))
copy(pathCopy, path)
@ -247,12 +159,12 @@ func back_trace_resource(list []int, i int, path []int, pathlist *[][]int) {
if list[i] == 0 {
path = append(path, 0)
back_trace_resource(list, i+1, path, pathlist)
Back_trace_resource(list, i+1, path, pathlist)
path = path[:len(path)-1]
} else {
for j := 1; j < list[i]+1; j++ {
path = append(path, j)
back_trace_resource(list, i+1, path, pathlist)
Back_trace_resource(list, i+1, path, pathlist)
path = path[:len(path)-1]
}
}

View File

@ -12,9 +12,11 @@
*/
package algo
package providerPricing
import "math"
import (
"math"
)
type Provider struct {
Pid int64

View File

@ -12,7 +12,7 @@
*/
package algo
package providerPricing
type Strategy struct {
Tasksolution []int //对应1种任务分配方案

View File

@ -12,7 +12,7 @@
*/
package algo
package providerPricing
type Task struct {
Tid int

View File

@ -18,7 +18,8 @@ import (
"bytes"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/api/pkg/response"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/models"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algo"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/strategies"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/utils"
"gorm.io/gorm"
"io"
@ -35,11 +36,11 @@ func NewCloudScheduler() *cloudScheduler {
return &cloudScheduler{}
}
func (cs *cloudScheduler) pickOptimalStrategy(task *algo.Task, providers ...*algo.Provider) (*algo.Strategy, error) {
func (cs *cloudScheduler) pickOptimalStrategy(task *providerPricing.Task, providers ...*providerPricing.Provider) (*providerPricing.Strategy, error) {
//调度算法
strategy := algo.NewK8sStrategy(task, providers...)
taskResult, err := algo.ScheduleWithFullCollaboration(strategy, strategy.ProviderList)
strategy := strategies.NewPricingStrategy(task, providers...)
taskResult, err := strategy.ScheduleWithFullCollaboration()
if err != nil {
return nil, err
}
@ -99,19 +100,19 @@ func (cs *cloudScheduler) UnMarshalK8sStruct(yamlString string, taskId int64, ns
return cloud
}
func (cs *cloudScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*algo.Task, []*algo.Provider) {
func (cs *cloudScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*providerPricing.Task, []*providerPricing.Provider) {
var proParams []providerParams
sqlstr := "SELECT SUM(a.disk_avail) as disk_avail,SUM(a.mem_avail) as mem_avail,SUM(a.cpu_total * a.cpu_usable) as cpu_avail,participant_id from (SELECT * from sc_node_avail_info where created_time in (SELECT MAX(created_time) as time from sc_node_avail_info where deleted_flag = 0 GROUP BY participant_id,node_name)) a GROUP BY a.participant_id"
dbEngin.Raw(sqlstr).Scan(&proParams)
var providerList []*algo.Provider
var providerList []*providerPricing.Provider
for _, p := range proParams {
provider := algo.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
provider := providerPricing.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
providerList = append(providerList, provider)
}
//replicas := task.Metadata.(map[string]interface{})["spec"].(map[string]interface{})["replicas"].(float64)
//t := algo.NewTask(0, int(replicas), 2, 75120000, 301214500, 1200, 2, 6, 2000)
//t := algorithm.NewTask(0, int(replicas), 2, 75120000, 301214500, 1200, 2, 6, 2000)
return nil, providerList
}

View File

@ -16,7 +16,7 @@ package scheduler
import (
"gitlink.org.cn/jcce-pcm/pcm-coordinator/api/pkg/response"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algo"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
"gorm.io/gorm"
"math/rand"
"time"
@ -24,8 +24,8 @@ import (
type scheduleService interface {
getNewStructForDb(task *response.TaskInfo, resource string, participantId int64) (interface{}, error)
pickOptimalStrategy(task *algo.Task, providers ...*algo.Provider) (*algo.Strategy, error)
genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*algo.Task, []*algo.Provider)
pickOptimalStrategy(task *providerPricing.Task, providers ...*providerPricing.Provider) (*providerPricing.Strategy, error)
genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*providerPricing.Task, []*providerPricing.Provider)
}
type providerParams struct {

View File

@ -18,7 +18,7 @@ import (
"gitlink.org.cn/jcce-pcm/pcm-coordinator/api/pkg/response"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/constants"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/models"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algo"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/utils"
"gorm.io/gorm"
)
@ -42,22 +42,22 @@ func (h *hpcScheduler) getNewStructForDb(task *response.TaskInfo, resource strin
return hpc, nil
}
func (h *hpcScheduler) pickOptimalStrategy(task *algo.Task, providers ...*algo.Provider) (*algo.Strategy, error) {
func (h *hpcScheduler) pickOptimalStrategy(task *providerPricing.Task, providers ...*providerPricing.Provider) (*providerPricing.Strategy, error) {
return nil, nil
}
func (h *hpcScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*algo.Task, []*algo.Provider) {
func (h *hpcScheduler) genTaskAndProviders(task *response.TaskInfo, dbEngin *gorm.DB) (*providerPricing.Task, []*providerPricing.Provider) {
var proParams []providerParams
sqlstr := "SELECT SUM(a.disk_avail) as disk_avail,SUM(a.mem_avail) as mem_avail,SUM(a.cpu_total * a.cpu_usable) as cpu_avail,participant_id from (SELECT * from sc_node_avail_info where created_time in (SELECT MAX(created_time) as time from sc_node_avail_info where deleted_flag = 0 GROUP BY participant_id,node_name)) a GROUP BY a.participant_id"
dbEngin.Raw(sqlstr).Scan(&proParams)
var providerList []*algo.Provider
var providerList []*providerPricing.Provider
for _, p := range proParams {
provider := algo.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
provider := providerPricing.NewProvider(p.Participant_id, p.Cpu_avail, p.Mem_avail, p.Disk_avail, 0.0, 0.0, 0.0)
providerList = append(providerList, provider)
}
t := algo.NewTask(0, 1, 2, 75120000, 301214500, 1200, 2, 6, 2000)
t := providerPricing.NewTask(0, 1, 2, 75120000, 301214500, 1200, 2, 6, 2000)
return t, providerList
}

View File

@ -19,7 +19,7 @@ import (
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/api/pkg/response"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algo"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/rpc/client/participantservice"
"gorm.io/gorm"
"sigs.k8s.io/yaml"
@ -180,7 +180,7 @@ func (s *scheduler) SaveToDb() error {
return nil
}
func (s *scheduler) obtainParamsForStrategy() (*algo.Task, []*algo.Provider, error) {
func (s *scheduler) obtainParamsForStrategy() (*providerPricing.Task, []*providerPricing.Provider, error) {
task, providerList := s.scheduleService.genTaskAndProviders(s.task, s.dbEngin)
if len(providerList) == 0 {
@ -190,7 +190,7 @@ func (s *scheduler) obtainParamsForStrategy() (*algo.Task, []*algo.Provider, err
return task, providerList, nil
}
func (s *scheduler) assignReplicasToResult(strategy *algo.Strategy, providerList []*algo.Provider) error {
func (s *scheduler) assignReplicasToResult(strategy *providerPricing.Strategy, providerList []*providerPricing.Provider) error {
if len(strategy.Tasksolution) == 0 {
return errors.New("调度失败, 未能获取调度结果")

View File

@ -0,0 +1,141 @@
/*
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 strategies
import (
"errors"
"gitlink.org.cn/jcce-pcm/pcm-coordinator/pkg/scheduler/algorithm/providerPricing"
)
type pricingStrategy struct {
ProviderList []*providerPricing.Provider
Task *providerPricing.Task
StrategyList []*providerPricing.Strategy
}
func NewPricingStrategy(task *providerPricing.Task, providers ...*providerPricing.Provider) *pricingStrategy {
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
}
//type strategyService interface {
// computeMaxScore() (*providerPricing.Task, error)
//}
func (ps *pricingStrategy) ScheduleWithFullCollaboration() (*providerPricing.Task, 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, nil
}