Skip to content
Merged
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
14 changes: 14 additions & 0 deletions pkg/device/amd/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@ func (amddevice *AMDDevices) Fit(devices []*device.DeviceUsage, request device.C
}
coreReq = dev.Totalcore * k.Coresreq / 100
coreReq = max(coreReq, 1)
// RDNA applies the CU mask per WGP, so the device plugin hands out
// whole WGPs; account for the same count.
if unit := cuPerWGP(dev.CustomInfo); unit > 1 {
coreReq = int32(min((int64(coreReq)+int64(unit)-1)/int64(unit)*int64(unit), int64(dev.Totalcore)))
}
coreReq = min(coreReq, dev.Totalcore)
} else if dev.Totalmem > 0 && memReq >= dev.Totalmem {
// Memreq omitted or zero means whole-card memory; treat core request as whole-card as well.
Expand Down Expand Up @@ -381,3 +386,12 @@ func (amddevice *AMDDevices) Fit(devices []*device.DeviceUsage, request device.C
}
return false, tmpDevs, common.GenReason(reason, len(devices))
}

// cuPerWGP returns how many CUs the device plugin allocates together, as
// published in the registration custominfo; 1 when absent.
func cuPerWGP(info map[string]any) int32 {
if v, ok := info["cuPerWGP"].(float64); ok && v > 1 && v <= math.MaxInt32 && v == math.Trunc(v) {
return int32(v)
}
return 1
}
29 changes: 29 additions & 0 deletions pkg/device/amd/device_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,35 @@ func TestDevices_Fit(t *testing.T) {
assert.Equal(t, "", reason)
})

t.Run("rounds cores up to whole WGPs on RDNA", func(t *testing.T) {
for _, tc := range []struct {
name string
total, used, coresReq int32
info map[string]any
wantCores int32
wantOK bool
}{
{"rdna odd cores", 64, 0, 5, map[string]any{"cuPerWGP": float64(2)}, 4, true},
{"cdna keeps single cus", 64, 0, 5, map[string]any{}, 3, true},
{"one-wgp apu", 2, 0, 50, map[string]any{"cuPerWGP": float64(2)}, 2, true},
{"huge wgp size does not overflow", 4, 0, 75, map[string]any{"cuPerWGP": float64(math.MaxInt32)}, 4, true},
{"fractional wgp size is ignored", 64, 0, 5, map[string]any{"cuPerWGP": 2.5}, 3, true},
{"apu wgp already taken", 2, 2, 50, map[string]any{"cuPerWGP": float64(2)}, 0, false},
} {
devices := []*device.DeviceUsage{{
ID: "dev-0", Count: 10, Totalmem: 1000, Totalcore: tc.total, Usedcores: tc.used,
Type: AMDDevice, Health: true, CustomInfo: tc.info,
}}
req := device.ContainerDeviceRequest{Nums: 1, Type: AMDDevice, Memreq: 100, Coresreq: tc.coresReq}
pod := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{Annotations: map[string]string{}}}
ok, got, _ := dev.Fit(devices, req, pod, &device.NodeInfo{}, &device.PodDevices{})
assert.Equal(t, tc.wantOK, ok, tc.name)
if tc.wantOK {
assert.Equal(t, tc.wantCores, got[AMDDevice][0].Usedcores, tc.name)
}
}
})

t.Run("retains the registered product type in the allocation", func(t *testing.T) {
const productType = "AMD_Instinct_MI300X_VF"
devices := []*device.DeviceUsage{
Expand Down
Loading