From 313edba1791fc476a871474c383874e6c99896ab Mon Sep 17 00:00:00 2001 From: Dmytro Aleksandrov Date: Sun, 18 Feb 2018 07:10:30 +0200 Subject: [PATCH 1/4] added PowerLimit() --- Makefile | 2 +- bindings.go | 23 +++++++++++++++++++++++ cmd/example/example.go | 12 ++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index b329e96..69398e4 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -PKG=github.com/mindprince/gonvml +PKG=github.com/aleksandrov/gonvml .PHONY: build build: diff --git a/bindings.go b/bindings.go index e204c26..58fe18b 100644 --- a/bindings.go +++ b/bindings.go @@ -111,6 +111,15 @@ nvmlReturn_t nvmlDeviceGetPowerUsage(nvmlDevice_t device, unsigned int *power) { return nvmlDeviceGetPowerUsageFunc(device, power); } +nvmlReturn_t (*nvmlDeviceGetPowerManagementLimitFunc)(nvmlDevice_t device, unsigned int *power); +nvmlReturn_t nvmlDeviceGetPowerManagementLimit(nvmlDevice_t device, unsigned int *power) { + if (nvmlDeviceGetPowerManagementLimitFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } + return nvmlDeviceGetPowerManagementLimitFunc(device, power); +} + + nvmlReturn_t (*nvmlDeviceGetTemperatureFunc)(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int *temp); nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int *temp) { if (nvmlDeviceGetTemperatureFunc == NULL) { @@ -185,6 +194,10 @@ nvmlReturn_t nvmlInit_dl(void) { if (nvmlDeviceGetPowerUsageFunc == NULL) { return NVML_ERROR_FUNCTION_NOT_FOUND; } + nvmlDeviceGetPowerManagementLimitFunc = dlsym(nvmlHandle, "nvmlDeviceGetPowerManagementLimit"); + if (nvmlDeviceGetPowerManagementLimitFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } nvmlDeviceGetTemperatureFunc = dlsym(nvmlHandle, "nvmlDeviceGetTemperature"); if (nvmlDeviceGetTemperatureFunc == NULL) { return NVML_ERROR_FUNCTION_NOT_FOUND; @@ -429,6 +442,16 @@ func (d Device) PowerUsage() (uint, error) { return uint(n), errorString(r) } +// PowerLimit returns the limit of power consumption. +func (d Device) PowerLimit() (uint, error) { + if C.nvmlHandle == nil { + return 0, errLibraryNotLoaded + } + var n C.uint + r := C.nvmlDeviceGetPowerManagementLimit(d.dev, &n) + return uint(n), errorString(r) +} + // AveragePowerUsage returns the power usage for this GPU and its associated circuitry // in milliwatts averaged over the samples collected in the last `since` duration. func (d Device) AveragePowerUsage(since time.Duration) (uint, error) { diff --git a/cmd/example/example.go b/cmd/example/example.go index 02425ac..1da5fed 100644 --- a/cmd/example/example.go +++ b/cmd/example/example.go @@ -20,7 +20,7 @@ import ( "fmt" "time" - "github.com/mindprince/gonvml" + "github.com/aleksandrov/gonvml" ) func main() { @@ -85,9 +85,17 @@ func main() { gpuUtilization, memoryUtilization, err := dev.UtilizationRates() if err != nil { fmt.Printf("\tdev.UtilizationRates() error: %v\n", err) + } else { + fmt.Printf("\tutilization.gpu: %v, utilization.memory: %v\n", gpuUtilization, memoryUtilization) + } + + powerLimit, err := dev.PowerLimit() + if err != nil { + fmt.Printf("\tdev.PowerLimit() error: %v\n", err) return } - fmt.Printf("\tutilization.gpu: %v, utilization.memory: %v\n", gpuUtilization, memoryUtilization) + fmt.Printf("\tpower.limit: %v\n", powerLimit) + powerDraw, err := dev.PowerUsage() if err != nil { From 875c9f7230644c53eb4085be56627f5a5869e1e1 Mon Sep 17 00:00:00 2001 From: Dmytro Aleksandrov Date: Sun, 18 Feb 2018 15:18:27 +0200 Subject: [PATCH 2/4] added PowerLimitConstraints() and SetPowerLimit() methods --- bindings.go | 47 +++++++++++++++++++++++++++++++++++++++++- cmd/example/example.go | 18 ++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/bindings.go b/bindings.go index 58fe18b..d63b15a 100644 --- a/bindings.go +++ b/bindings.go @@ -119,6 +119,22 @@ nvmlReturn_t nvmlDeviceGetPowerManagementLimit(nvmlDevice_t device, unsigned int return nvmlDeviceGetPowerManagementLimitFunc(device, power); } +nvmlReturn_t (*nvmlDeviceGetPowerManagementLimitConstraintsFunc)(nvmlDevice_t device, unsigned int *minLimit, unsigned int *maxLimit); +nvmlReturn_t nvmlDeviceGetPowerManagementLimitConstraints(nvmlDevice_t device, unsigned int *minLimit, unsigned int *maxLimit) { + if (nvmlDeviceGetPowerManagementLimitConstraintsFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } + return nvmlDeviceGetPowerManagementLimitConstraintsFunc(device, minLimit, maxLimit); +} + +nvmlReturn_t (*nvmlDeviceSetPowerManagementLimitFunc)(nvmlDevice_t device, unsigned int power); +nvmlReturn_t nvmlDeviceSetPowerManagementLimit(nvmlDevice_t device, unsigned int power) { + if (nvmlDeviceSetPowerManagementLimitFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } + return nvmlDeviceSetPowerManagementLimitFunc(device, power); +} + nvmlReturn_t (*nvmlDeviceGetTemperatureFunc)(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int *temp); nvmlReturn_t nvmlDeviceGetTemperature(nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int *temp) { @@ -198,6 +214,14 @@ nvmlReturn_t nvmlInit_dl(void) { if (nvmlDeviceGetPowerManagementLimitFunc == NULL) { return NVML_ERROR_FUNCTION_NOT_FOUND; } + nvmlDeviceGetPowerManagementLimitConstraintsFunc = dlsym(nvmlHandle, "nvmlDeviceGetPowerManagementLimitConstraints"); + if (nvmlDeviceGetPowerManagementLimitConstraintsFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } + nvmlDeviceSetPowerManagementLimitFunc = dlsym(nvmlHandle, "nvmlDeviceSetPowerManagementLimit"); + if (nvmlDeviceSetPowerManagementLimitFunc == NULL) { + return NVML_ERROR_FUNCTION_NOT_FOUND; + } nvmlDeviceGetTemperatureFunc = dlsym(nvmlHandle, "nvmlDeviceGetTemperature"); if (nvmlDeviceGetTemperatureFunc == NULL) { return NVML_ERROR_FUNCTION_NOT_FOUND; @@ -442,7 +466,7 @@ func (d Device) PowerUsage() (uint, error) { return uint(n), errorString(r) } -// PowerLimit returns the limit of power consumption. +// PowerLimit retrieves the power management limit associated with this device. func (d Device) PowerLimit() (uint, error) { if C.nvmlHandle == nil { return 0, errLibraryNotLoaded @@ -452,6 +476,27 @@ func (d Device) PowerLimit() (uint, error) { return uint(n), errorString(r) } +// PowerLimitConstraints retrieves information about possible values of power management limits on this device. +func (d Device) PowerLimitConstraints() (uint, uint, error) { + if C.nvmlHandle == nil { + return 0, 0, errLibraryNotLoaded + } + var min C.uint + var max C.uint + r := C.nvmlDeviceGetPowerManagementLimitConstraints(d.dev, &min, &max) + return uint(min), uint(max), errorString(r) +} + +// Set new power limit of this device. +func (d Device) SetPowerLimit(pl uint) error { + + if C.nvmlHandle == nil { + return errLibraryNotLoaded + } + r := C.nvmlDeviceSetPowerManagementLimit(d.dev, C.uint(pl)) + return errorString(r) +} + // AveragePowerUsage returns the power usage for this GPU and its associated circuitry // in milliwatts averaged over the samples collected in the last `since` duration. func (d Device) AveragePowerUsage(since time.Duration) (uint, error) { diff --git a/cmd/example/example.go b/cmd/example/example.go index 1da5fed..fda7da2 100644 --- a/cmd/example/example.go +++ b/cmd/example/example.go @@ -92,10 +92,24 @@ func main() { powerLimit, err := dev.PowerLimit() if err != nil { fmt.Printf("\tdev.PowerLimit() error: %v\n", err) - return + } else { + fmt.Printf("\tpower.limit: %v\n", powerLimit) } - fmt.Printf("\tpower.limit: %v\n", powerLimit) + minLimit, maxLimit, err := dev.PowerLimitConstraints() + if err != nil { + fmt.Printf("\tdev.PowerLimitConstraints() error: %v\n", err) + } else { + fmt.Printf("\tpower.min_limit: %v\n", minLimit / 1000) + fmt.Printf("\tpower.max_limit: %v\n", maxLimit / 1000) + } + + err = dev.SetPowerLimit(180000) + if err != nil { + fmt.Printf("\tdev.SetPowerLimit(%v) error: %v\n", powerLimit/1000, err) + } else { + fmt.Printf("\tnew power.limit: %v\n", powerLimit/1000) + } powerDraw, err := dev.PowerUsage() if err != nil { From b92d63167dab3551381977c873fca937c596a9ab Mon Sep 17 00:00:00 2001 From: Dmytro Aleksandrov Date: Sat, 31 Mar 2018 14:42:00 +0300 Subject: [PATCH 3/4] reverted back package name --- Makefile | 2 +- cmd/example/example.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 69398e4..b329e96 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -PKG=github.com/aleksandrov/gonvml +PKG=github.com/mindprince/gonvml .PHONY: build build: diff --git a/cmd/example/example.go b/cmd/example/example.go index fda7da2..0530752 100644 --- a/cmd/example/example.go +++ b/cmd/example/example.go @@ -20,7 +20,7 @@ import ( "fmt" "time" - "github.com/aleksandrov/gonvml" + "github.com/mindprince/gonvml" ) func main() { From 74456e815e17f76d474014fd2dada5ffc4ef638d Mon Sep 17 00:00:00 2001 From: Dmytro Aleksandrov Date: Sat, 31 Mar 2018 14:48:46 +0300 Subject: [PATCH 4/4] reverted back some changes --- cmd/example/example.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/example/example.go b/cmd/example/example.go index 0530752..50168a4 100644 --- a/cmd/example/example.go +++ b/cmd/example/example.go @@ -85,9 +85,9 @@ func main() { gpuUtilization, memoryUtilization, err := dev.UtilizationRates() if err != nil { fmt.Printf("\tdev.UtilizationRates() error: %v\n", err) - } else { - fmt.Printf("\tutilization.gpu: %v, utilization.memory: %v\n", gpuUtilization, memoryUtilization) + return } + fmt.Printf("\tutilization.gpu: %v, utilization.memory: %v\n", gpuUtilization, memoryUtilization) powerLimit, err := dev.PowerLimit() if err != nil {