Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/unreleased/fixed-20261025-025826.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
kind: Fixed
body: |-
Allow the binder-translated NvFractions limit next to gpu-fraction when gpu-memory.portion.limit is set

custom:
Author: ZeXi0308
Issue: "28"
6 changes: 5 additions & 1 deletion utilities/resources/gpu_sharing_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ func ValidateGPUFractionRequest(pod *v1.Pod) error {

// A legacy gpu-memory request may accompany a translated shorthand limit.
_, hasMemoryLimitShorthand := pod.Annotations[constants.GpuMemoryLimit]
if req.Limit != nil && (hasLegacyFraction || (hasLegacyMemory && !hasMemoryLimitShorthand)) {
// A legacy gpu-fraction request may accompany the NvFractions limit the binder
// derives from gpu-memory.portion.limit at bind time.
_, _, hasPortionLimit := ExtractGpuMemoryPortionLimitAnnotation(pod)
if req.Limit != nil &&
((hasLegacyFraction && !hasPortionLimit) || (hasLegacyMemory && !hasMemoryLimitShorthand)) {
return fmt.Errorf("cannot combine %s limit annotation with %s or %s annotation",
constants.NvFractionsAnnotationPrefix, constants.GpuFraction, constants.GpuMemory)
}
Expand Down
61 changes: 61 additions & 0 deletions utilities/resources/gpu_sharing_validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,67 @@ func TestValidateGpuMemoryPortionLimitAnnotation(t *testing.T) {
}
}

func TestValidateGPUFractionRequest_TranslatedLimits(t *testing.T) {
nvRequestKey := CalcGpuFractionAnnotationForContainer("container-0")
nvLimitKey := CalcGpuFractionLimitAnnotationForContainer("container-0")
portionLimitKey := CalcGpuMemoryPortionLimitAnnotationForContainer("container-0")

tests := []struct {
name string
annotations map[string]string
wantErrContaining string
}{
{
name: "gpu-fraction with portion limit accepts the binder-translated NvFractions limit",
annotations: map[string]string{
constants.GpuFraction: "0.5",
portionLimitKey: "0.8",
nvRequestKey: "1000Mi",
nvLimitKey: "1600Mi",
},
},
{
name: "gpu-fraction without portion limit rejects an NvFractions limit",
annotations: map[string]string{
constants.GpuFraction: "0.5",
nvRequestKey: "1000Mi",
nvLimitKey: "1600Mi",
},
wantErrContaining: "cannot combine",
},
{
name: "gpu-memory with gpu-memory.limit accepts the translated NvFractions limit",
annotations: map[string]string{
constants.GpuMemory: "1000",
constants.GpuMemoryLimit: "1600Mi",
nvRequestKey: "1000Mi",
nvLimitKey: "1600Mi",
},
},
{
name: "gpu-memory without gpu-memory.limit rejects an NvFractions limit",
annotations: map[string]string{
constants.GpuMemory: "1000",
nvRequestKey: "1000Mi",
nvLimitKey: "1600Mi",
},
wantErrContaining: "cannot combine",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{Annotations: tt.annotations},
Spec: v1.PodSpec{Containers: []v1.Container{{Name: "container-0"}}},
}

err := ValidateGPUFractionRequest(pod)
assertErrorContains(t, err, tt.wantErrContaining)
})
}
}

func TestValidateGPUFractionRequest_ComputeSharingMode(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading