diff --git a/go.mod b/go.mod index 0e6e2a6..0f15b16 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/containerd/continuity v0.0.0-20210315143101-93e15499afd5 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect - github.com/davecgh/go-spew v1.1.1 + github.com/davecgh/go-spew v1.1.1 // indirect github.com/docker/distribution v2.7.1+incompatible // indirect github.com/docker/docker v20.10.0-beta1.0.20201113105859-b6bfff2a628f+incompatible github.com/docker/go-connections v0.4.0 @@ -24,6 +24,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/mxpv/nvml-go v0.0.0-20180227003457-e07f8c26812d github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 diff --git a/go.sum b/go.sum index 49b688f..efd683f 100644 --- a/go.sum +++ b/go.sum @@ -424,6 +424,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/mxpv/nvml-go v0.0.0-20180227003457-e07f8c26812d h1:lQo1zUtnGr52K2a+Ll3DNDoukmPeuHK11baUNGRDSt0= +github.com/mxpv/nvml-go v0.0.0-20180227003457-e07f8c26812d/go.mod h1:PS1oTOPfvtFjl9T7nduA/RYrIpqtRh2Nvk++rQCZ2q8= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= diff --git a/server/gopsutil.go b/server/gopsutil.go index 323e361..fc95b34 100644 --- a/server/gopsutil.go +++ b/server/gopsutil.go @@ -14,6 +14,7 @@ type SysInfo struct { CPU string `bson:cpu` RAM uint64 `bson:ram` Disk uint64 `bson:disk` + GPU *Query `xml: GpuInfo` } func ServerInfo() interface{}{ @@ -38,6 +39,12 @@ func ServerInfo() interface{}{ info.RAM = vmStat.Total / 1024 / 1024 info.Disk = diskStat.Total / 1024 / 1024 + gpu, err := GPUInfo() + + if err == nil { + info.GPU = gpu + } + return info } diff --git a/server/gpu.go b/server/gpu.go new file mode 100644 index 0000000..1164c1e --- /dev/null +++ b/server/gpu.go @@ -0,0 +1,51 @@ +package server + +import ( + "encoding/xml" + "os/exec" +) + +type Query struct { + DriveVersion string `xml:"driver_version"` + Gpu Gpu `xml:"gpu"` +} + +type Gpu struct{ + GpuName string `xml:"product_name"` + BiosVersion string `xml:"vbios_version"` + FanSpeed string `xml:"fan_speed"` + Utilization GpuUtilization `xml:"utilization"` + Temperature GpuTemperature `xml:"temperature"` + Clock GpuClock `xml:"clocks"` +} + +type GpuUtilization struct { + GpuUsage string `xml:"gpu_util"` + MemoryUsage string `xml:"memory_util"` +} + +type GpuTemperature struct { + GpuTemp string `xml:"gpu_temp"` +} + +type GpuClock struct { + GpuClock string `xml:"graphics_clock"` + GpuMemClock string `xml:"mem_clock"` +} + +func GPUInfo()(*Query,error) { + out, err := exec.Command("nvidia-smi", "-q", "-x").Output() + + if err != nil { + return nil,err + } + + var gpu Query + err = xml.Unmarshal(out, &gpu) + + if err != nil { + return nil,err + } + + return &gpu,nil +} \ No newline at end of file diff --git a/server/gpu_test.go b/server/gpu_test.go new file mode 100644 index 0000000..78f0a7b --- /dev/null +++ b/server/gpu_test.go @@ -0,0 +1,16 @@ +package server + +import ( + "fmt" + "testing" +) + +func TestGpuOutput(t *testing.T) { + gpu, err := GPUInfo() + + if err != nil { + t.Error(err) + } + + fmt.Print(gpu.Gpu.GpuName) +} diff --git a/server/test/test.go b/server/test/test.go new file mode 100644 index 0000000..ec254a0 --- /dev/null +++ b/server/test/test.go @@ -0,0 +1,60 @@ +package main + +import ( + "fmt" + "log" + "os" + "text/template" + + "github.com/NVIDIA/gpu-monitoring-tools/bindings/go/nvml" +) + +const ( + DEVICEINFO = `UUID : {{.UUID}} +Model : {{or .Model "N/A"}} +Path : {{.Path}} +Power : {{if .Power}}{{.Power}} W{{else}}N/A{{end}} +Memory : {{if .Memory}}{{.Memory}} MiB{{else}}N/A{{end}} +CudaComputeCap : {{if .CudaComputeCapability.Major}}{{.CudaComputeCapability.Major}}.{{.CudaComputeCapability.Minor}}{{else}}N/A{{end}} +CPU Affinity : {{if .CPUAffinity}}NUMA node{{.CPUAffinity}}{{else}}N/A{{end}} +Bus ID : {{.PCI.BusID}} +BAR1 : {{if .PCI.BAR1}}{{.PCI.BAR1}} MiB{{else}}N/A{{end}} +Bandwidth : {{if .PCI.Bandwidth}}{{.PCI.Bandwidth}} MB/s{{else}}N/A{{end}} +Cores : {{if .Clocks.Cores}}{{.Clocks.Cores}} MHz{{else}}N/A{{end}} +Memory : {{if .Clocks.Memory}}{{.Clocks.Memory}} MHz{{else}}N/A{{end}} +P2P Available : {{if not .Topology}}None{{else}}{{range .Topology}} + {{.BusID}} - {{(.Link.String)}}{{end}}{{end}} +--------------------------------------------------------------------- +` +) + +func main() { + nvml.Init() + defer nvml.Shutdown() + + count, err := nvml.GetDeviceCount() + if err != nil { + log.Panicln("Error getting device count:", err) + } + + driverVersion, err := nvml.GetDriverVersion() + if err != nil { + log.Panicln("Error getting driver version:", err) + } + + t := template.Must(template.New("Device").Parse(DEVICEINFO)) + + fmt.Printf("Driver Version : %5v\n", driverVersion) + for i := uint(0); i < count; i++ { + device, err := nvml.NewDevice(i) + if err != nil { + log.Panicf("Error getting device %d: %v\n", i, err) + } + + fmt.Printf("GPU %12s %d\n", ":", i) + err = t.Execute(os.Stdout, device) + if err != nil { + log.Panicln("Template error:", err) + } + } +}