1- // Copyright 2021-2022 Intel Corporation. All Rights Reserved.
1+ // Copyright 2021-2023 Intel Corporation. All Rights Reserved.
22//
33// Licensed under the Apache License, Version 2.0 (the "License");
44// you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@ import (
4444 "os"
4545 "path/filepath"
4646 "strconv"
47+ "strings"
4748
4849 "golang.org/x/sys/unix"
4950)
@@ -61,6 +62,9 @@ const (
6162 devNullMajor = 1
6263 devNullMinor = 3
6364 devNullType = unix .S_IFCHR
65+ // GPU connectivity
66+ maxK8sLabelSize = 63
67+ fullyConnected = "FULL"
6468)
6569
6670var verbose bool
@@ -289,6 +293,85 @@ func generateDriFiles(opts genOptions) {
289293 }
290294 }
291295 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+ }
292375}
293376
294377// getOptions parses options from given JSON file, validates and returns them.
0 commit comments