diff --git a/scheduler/complex/potassium.go b/scheduler/complex/potassium.go index 8bf88d182..f017ed273 100644 --- a/scheduler/complex/potassium.go +++ b/scheduler/complex/potassium.go @@ -197,7 +197,7 @@ func (m *Potassium) ReselectCPUNodes(ctx context.Context, scheduleInfo resourcet func cpuReallocPlan(scheduleInfo resourcetypes.ScheduleInfo, quota float64, CPU types.CPUMap, sharebase int64) (resourcetypes.ScheduleInfo, float64, types.CPUMap) { affinityPlan := make(types.CPUMap) - diff := int64(quota*float64(sharebase)) - CPU.Total() + diff := types.RoundToInt(quota*float64(sharebase)) - CPU.Total() // sort by pieces cpuIDs := []string{} for cpuID := range CPU { @@ -226,7 +226,7 @@ func cpuReallocPlan(scheduleInfo resourcetypes.ScheduleInfo, quota float64, CPU } // expand, prioritize full cpus - needPieces := int64(quota * float64(sharebase)) + needPieces := types.RoundToInt(quota * float64(sharebase)) for i := len(cpuIDs) - 1; i >= 0; i-- { cpuID := cpuIDs[i] if needPieces == 0 { @@ -243,10 +243,10 @@ func cpuReallocPlan(scheduleInfo resourcetypes.ScheduleInfo, quota float64, CPU // fragments, try to find complement if available := scheduleInfo.CPU[cpuID]; available == sharebase-CPU[cpuID] { - expand := utils.Min64(available, needPieces) + expand := utils.Min64(available, needPieces-CPU[cpuID]) affinityPlan[cpuID] = CPU[cpuID] + expand scheduleInfo.CPU[cpuID] -= expand - needPieces -= sharebase + needPieces -= affinityPlan[cpuID] continue } diff --git a/scheduler/complex/resource.go b/scheduler/complex/resource.go index 7527daa39..3f1112e1e 100644 --- a/scheduler/complex/resource.go +++ b/scheduler/complex/resource.go @@ -5,6 +5,7 @@ import ( "sort" "github.com/projecteru2/core/types" + "github.com/projecteru2/core/utils" ) type resourceInfo struct { @@ -121,7 +122,10 @@ func (h *host) getFragmentResult(fragment int64, resources []resourceInfo) []typ resourceMaps := h.getFragmentsResult(resources, fragment) result := make([]types.ResourceMap, len(resourceMaps)) for i, resourceMap := range resourceMaps { - result[i] = resourceMap[0] + result[i] = types.ResourceMap{} + for id, pieces := range resourceMap[0] { + result[i][id] = pieces + } } // to pass tests due to new algorithm returns unsorted list @@ -259,16 +263,19 @@ func (h *host) getFullResult(full int, resources []resourceInfo) []types.Resourc func (h *host) distributeOneRation(ration float64, maxShare int) []types.ResourceMap { ration *= float64(h.share) - fullRequire := int64(ration) / int64(h.share) - fragmentRequire := int64(ration) % int64(h.share) + fullRequire := types.RoundToInt(ration) / int64(h.share) + fragmentRequire := types.RoundToInt(ration) % int64(h.share) if fullRequire == 0 { - if maxShare == -1 { + if maxShare < 0 { // 这个时候就把所有的资源都当成碎片 maxShare = len(h.full) + len(h.fragment) } + maxShare = utils.Min(maxShare, len(h.full)+len(h.fragment)) diff := maxShare - len(h.fragment) - h.fragment = append(h.fragment, h.full[:diff]...) + if diff > 0 { + h.fragment = append(h.fragment, h.full[:diff]...) + } return h.getFragmentResult(fragmentRequire, h.fragment) } diff --git a/types/helper.go b/types/helper.go index 0da15b75b..e3ee73bc7 100644 --- a/types/helper.go +++ b/types/helper.go @@ -6,3 +6,8 @@ import "math" func Round(f float64) float64 { return math.Round(f*1000000000) / 1000000000 } + +// RoundToInt for float64 to int +func RoundToInt(f float64) int64 { + return int64(math.Round(f)) +} diff --git a/types/helper_test.go b/types/helper_test.go index 87b67548e..9138f3225 100644 --- a/types/helper_test.go +++ b/types/helper_test.go @@ -16,3 +16,12 @@ func TestRound(t *testing.T) { a = 19.99998 assert.InDelta(t, (Round(a)), 19.99998, 1e-6) } + +func TestRoundToInt(t *testing.T) { + a := 0.0199999998 + assert.EqualValues(t, RoundToInt(a), 0) + a = 0.1999998 + assert.EqualValues(t, RoundToInt(a), 0) + a = 1.999998 + assert.EqualValues(t, RoundToInt(a), 2) +}