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,86 @@ 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
+
312
+ log .Printf ("XELINK: generated xelink sidecar label file, using (GPUs: %d, Tiles: %d, Topology: %s)" , gpus , tiles , topology )
313
+ }
314
+
315
+ func buildConnectionList (gpus , tiles int ) string {
316
+ var nodes = make ([]string , 0 )
317
+
318
+ for mm := 0 ; mm < gpus ; mm ++ {
319
+ for nn := 0 ; nn < tiles ; nn ++ {
320
+ nodes = append (nodes , fmt .Sprintf ("%d.%d" , mm , nn ))
321
+ }
322
+ }
323
+
324
+ var links = make (map [string ]bool , 0 )
325
+
326
+ var smap = make ([]string , 0 )
327
+
328
+ for _ , from := range nodes {
329
+ for _ , to := range nodes {
330
+ // no self links, TODO ignore in-gpu xelinks
331
+ if to == from {
332
+ continue
333
+ }
334
+
335
+ link := fmt .Sprintf ("%s-%s" , to , from )
336
+
337
+ reverselink := fmt .Sprintf ("%s-%s" , from , to )
338
+ if _ , exists := links [reverselink ]; ! exists {
339
+ links [link ] = true
340
+
341
+ smap = append (smap , link )
342
+ }
343
+ }
344
+ }
345
+
346
+ return strings .Join (smap , "_" )
347
+ }
348
+
349
+ func saveSideCarFile (connections string ) {
350
+ f , err := os .Create ("xpum-sidecar-labels.txt" )
351
+ if err != nil {
352
+ panic (err )
353
+ }
354
+ defer f .Close ()
355
+
356
+ // Write first line without Z prefix
357
+ line := fmt .Sprintf ("xpumanager.intel.com/xe-links=%s" , connections [:min (len (connections ), maxK8sLabelSize )])
358
+ fmt .Println (line )
359
+
360
+ if _ , err := f .WriteString (line + "\n " ); err != nil {
361
+ panic (err )
362
+ }
363
+
364
+ index := 2
365
+
366
+ // Write next lines with Z prefix
367
+ for i := maxK8sLabelSize ; i < len (connections ); i += (maxK8sLabelSize - 1 ) {
368
+ line := fmt .Sprintf ("xpumanager.intel.com/xe-links%d=Z%s" , index , connections [i :min (len (connections ), i + maxK8sLabelSize - 1 )])
369
+ fmt .Println (line )
370
+
371
+ if _ , err := f .WriteString (line + "\n " ); err != nil {
372
+ panic (err )
373
+ }
374
+ index ++
375
+ }
292
376
}
293
377
294
378
// getOptions parses options from given JSON file, validates and returns them.
0 commit comments