1
- // Copyright 2021-2022 Intel Corporation. All Rights Reserved.
1
+ // Copyright 2021-2023 Intel Corporation. All Rights Reserved.
2
2
//
3
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
4
// you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ import (
44
44
"os"
45
45
"path/filepath"
46
46
"strconv"
47
+ "strings"
47
48
48
49
"golang.org/x/sys/unix"
49
50
)
@@ -61,6 +62,9 @@ const (
61
62
devNullMajor = 1
62
63
devNullMinor = 3
63
64
devNullType = unix .S_IFCHR
65
+ // GPU connectivity
66
+ maxK8sLabelSize = 63
67
+ fullyConnected = "FULL"
64
68
)
65
69
66
70
var verbose bool
@@ -289,6 +293,85 @@ func generateDriFiles(opts genOptions) {
289
293
}
290
294
}
291
295
log .Printf ("Done, created %d dirs, %d devices and %d files." , opts .dirs , opts .devs , opts .files )
296
+
297
+ makeXelinkSideCar (opts )
298
+ }
299
+
300
+ func makeXelinkSideCar (opts genOptions ) {
301
+ topology := opts .Capabilities ["connection-topology" ]
302
+ gpus := opts .DevCount
303
+ tiles := opts .TilesPerDev
304
+ connections := opts .Capabilities ["connections" ]
305
+
306
+ if topology != fullyConnected {
307
+ saveSideCarFile (connections )
308
+ } else {
309
+ saveSideCarFile (buildConnectionList (gpus , tiles ))
310
+ }
311
+ log .Printf ("XELINK: generated xelink sidecar label file, using (GPUs: %d, Tiles: %d, Topology: %s)" , gpus , tiles , topology )
312
+ }
313
+
314
+ func buildConnectionList (gpus , tiles int ) string {
315
+ var nodes = make ([]string , 0 )
316
+
317
+ for mm := 0 ; mm < gpus ; mm ++ {
318
+ for nn := 0 ; nn < tiles ; nn ++ {
319
+ nodes = append (nodes , fmt .Sprintf ("%d.%d" , mm , nn ))
320
+ }
321
+ }
322
+
323
+ var links = make (map [string ]bool , 0 )
324
+
325
+ var smap = make ([]string , 0 )
326
+
327
+ for _ , from := range nodes {
328
+ for _ , to := range nodes {
329
+ // no self links, TODO ignore in-gpu xelinks
330
+ if to == from {
331
+ continue
332
+ }
333
+
334
+ link := fmt .Sprintf ("%s-%s" , to , from )
335
+
336
+ reverselink := fmt .Sprintf ("%s-%s" , from , to )
337
+ if _ , exists := links [reverselink ]; ! exists {
338
+ links [link ] = true
339
+
340
+ smap = append (smap , link )
341
+ }
342
+ }
343
+ }
344
+
345
+ return strings .Join (smap , "_" )
346
+ }
347
+
348
+ func saveSideCarFile (connections string ) {
349
+ f , err := os .Create ("xpum-sidecar-labels.txt" )
350
+ if err != nil {
351
+ panic (err )
352
+ }
353
+ defer f .Close ()
354
+
355
+ // Write first line without Z prefix
356
+ line := fmt .Sprintf ("xpumanager.intel.com/xe-links=%s" , connections [:min (len (connections ), maxK8sLabelSize )])
357
+ fmt .Println (line )
358
+
359
+ if _ , err := f .WriteString (line + "\n " ); err != nil {
360
+ panic (err )
361
+ }
362
+
363
+ index := 2
364
+
365
+ // Write next lines with Z prefix
366
+ for i := maxK8sLabelSize ; i < len (connections ); i += (maxK8sLabelSize - 1 ) {
367
+ line := fmt .Sprintf ("xpumanager.intel.com/xe-links%d=Z%s" , index , connections [i :min (len (connections ), i + maxK8sLabelSize - 1 )])
368
+ fmt .Println (line )
369
+
370
+ if _ , err := f .WriteString (line + "\n " ); err != nil {
371
+ panic (err )
372
+ }
373
+ index ++
374
+ }
292
375
}
293
376
294
377
// getOptions parses options from given JSON file, validates and returns them.
0 commit comments