nvml-wrapper-0.11.0/.cargo_vcs_info.json 0000644 00000000152 00000000001 0013543 0 ustar {
"git": {
"sha1": "f07acbc43338ad87b6ba1222f8d81bb483a1929e"
},
"path_in_vcs": "nvml-wrapper"
} nvml-wrapper-0.11.0/Cargo.lock 0000644 00000021410 00000000001 0011516 0 ustar # This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
dependencies = [
"serde",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "darling"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc5d6b04b3fd0ba9926f945895de7d806260a2d7431ba82e7edaecb043c4c6b8"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e48a959bcd5c761246f5d090ebc2fbf7b9cd527a492b07a67510c108f1e7e3"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "libc"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libloading"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
dependencies = [
"cfg-if",
"windows-sys",
]
[[package]]
name = "nvml-wrapper"
version = "0.11.0"
dependencies = [
"bitflags",
"libloading",
"nvml-wrapper-sys",
"pretty-bytes",
"serde",
"serde_derive",
"static_assertions",
"thiserror",
"wrapcenum-derive",
]
[[package]]
name = "nvml-wrapper-sys"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd23dbe2eb8d8335d2bce0299e0a07d6a63c089243d626ca75b770a962ff49e6"
dependencies = [
"libloading",
]
[[package]]
name = "pretty-bytes"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "009d6edd2c1dbf2e1c0cd48a2f7766e03498d49ada7109a01c6911815c685316"
dependencies = [
"atty",
"getopts",
]
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "serde"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-width"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "wrapcenum-derive"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76ff259533532054cfbaefb115c613203c73707017459206380f03b3b3f266e"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
nvml-wrapper-0.11.0/Cargo.toml 0000644 00000003504 00000000001 0011545 0 ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.60.0"
name = "nvml-wrapper"
version = "0.11.0"
authors = ["Cldfire"]
build = false
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "A safe and ergonomic Rust wrapper for the NVIDIA Management Library"
documentation = "https://docs.rs/nvml-wrapper"
readme = "README.md"
keywords = [
"nvidia",
"gpu",
"managment",
"monitoring",
"hardware",
]
categories = [
"api-bindings",
"hardware-support",
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/Cldfire/nvml-wrapper"
[features]
default = []
legacy-functions = ["nvml-wrapper-sys/legacy-functions"]
serde = [
"dep:serde",
"dep:serde_derive",
"bitflags/serde",
]
[lib]
name = "nvml_wrapper"
path = "src/lib.rs"
[[example]]
name = "basic_usage"
path = "examples/basic_usage.rs"
[[example]]
name = "event_loop"
path = "examples/event_loop.rs"
[dependencies.bitflags]
version = "2.4.0"
[dependencies.libloading]
version = "0.8.1"
[dependencies.nvml-wrapper-sys]
version = "0.9.0"
[dependencies.serde]
version = "1.0"
optional = true
[dependencies.serde_derive]
version = "1.0"
optional = true
[dependencies.static_assertions]
version = "1.1"
[dependencies.thiserror]
version = "1.0"
[dependencies.wrapcenum-derive]
version = "0.4.1"
[dev-dependencies.pretty-bytes]
version = "0.2"
nvml-wrapper-0.11.0/Cargo.toml.orig 0000644 0000000 0000000 00000001733 10461020230 0015230 0 ustar 0000000 0000000 [package]
name = "nvml-wrapper"
version = "0.11.0"
authors = ["Cldfire"]
description = "A safe and ergonomic Rust wrapper for the NVIDIA Management Library"
readme = "../README.md"
documentation = "https://docs.rs/nvml-wrapper"
repository = "https://github.com/Cldfire/nvml-wrapper"
license = "MIT OR Apache-2.0"
edition = "2021"
rust-version = "1.60.0"
keywords = ["nvidia", "gpu", "managment", "monitoring", "hardware"]
categories = ["api-bindings", "hardware-support"]
[features]
default = []
legacy-functions = ["nvml-wrapper-sys/legacy-functions"]
serde = ["dep:serde", "dep:serde_derive", "bitflags/serde"]
[dependencies]
thiserror = "1.0"
bitflags = "2.4.0"
serde = { version = "1.0", optional = true }
serde_derive = { version = "1.0", optional = true }
nvml-wrapper-sys = { version = "0.9.0", path = "../nvml-wrapper-sys" }
wrapcenum-derive = "0.4.1"
libloading = "0.8.1"
static_assertions = "1.1"
[dev-dependencies]
# Used in the `basic_usage` example
pretty-bytes = "0.2"
nvml-wrapper-0.11.0/LICENSE-APACHE 0000644 0000000 0000000 00000026133 10461020230 0014266 0 ustar 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. nvml-wrapper-0.11.0/LICENSE-MIT 0000644 0000000 0000000 00000002053 10461020230 0013771 0 ustar 0000000 0000000 MIT License
Copyright (c) 2017 Jarek Samic
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. nvml-wrapper-0.11.0/README.md 0000644 0000000 0000000 00000010574 10461020230 0013623 0 ustar 0000000 0000000 # nvml-wrapper
[](https://docs.rs/nvml-wrapper)
[](https://crates.io/crates/nvml-wrapper)
[](https://crates.io/crates/nvml-wrapper)

[](https://deps.rs/repo/github/cldfire/nvml-wrapper)
A safe and ergonomic Rust wrapper for the [NVIDIA Management Library][nvml] (NVML),
a C-based programmatic interface for monitoring and managing various states within
NVIDIA GPUs.
```rust
use nvml_wrapper::Nvml;
let nvml = Nvml::init()?;
// Get the first `Device` (GPU) in the system
let device = nvml.device_by_index(0)?;
let brand = device.brand()?; // GeForce on my system
let fan_speed = device.fan_speed(0)?; // Currently 17% on my system
let power_limit = device.enforced_power_limit()?; // 275k milliwatts on my system
let encoder_util = device.encoder_utilization()?; // Currently 0 on my system; Not encoding anything
let memory_info = device.memory_info()?; // Currently 1.63/6.37 GB used on my system
// ... and there's a whole lot more you can do. Most everything in NVML is wrapped and ready to go
```
_try the [`basic_usage`](nvml-wrapper/examples/basic_usage.rs) example on your system_
NVML is intended to be a platform for building 3rd-party applications, and is
also the underlying library for NVIDIA's nvidia-smi tool.
## Usage
`nvml-wrapper` builds on top of generated bindings for NVML that make use of the
[`libloading`][libloading] crate. This means the NVML library gets loaded upon
calling `Nvml::init` and can return an error if NVML isn't present, making it
possible to drop NVIDIA-related features in your code at runtime on systems that
don't have relevant hardware.
Successful execution of `Nvml::init` means:
* The NVML library was present on the system and able to be opened
* The function symbol to initialize NVML was loaded and called successfully
* An attempt has been made to load all other NVML function symbols
Every function you call thereafter will individually return an error if it couldn't
be loaded from the NVML library during the `Nvml::init` call.
Note that it's not advised to repeatedly call `Nvml::init` as the constructor
has to perform all the work of loading the function symbols from the library
each time it gets called. Instead, call `Nvml::init` once and store the resulting
`Nvml` instance somewhere to be accessed throughout the lifetime of your program
(perhaps in a [`once_cell`][once_cell]).
## NVML Support
This wrapper is being developed against and currently supports NVML version
11. Each new version of NVML is guaranteed to be backwards-compatible according
to NVIDIA, so this wrapper should continue to work without issue regardless of
NVML version bumps.
### Legacy Functions
Sometimes there will be function-level API version bumps in new NVML releases.
For example:
```text
nvmlDeviceGetComputeRunningProcesses
nvmlDeviceGetComputeRunningProcesses_v2
nvmlDeviceGetComputeRunningProcesses_v3
```
The older versions of the functions will generally continue to work with the
newer NVML releases; however, the newer function versions will not work with
older NVML installs.
By default this wrapper only provides access to the newest function versions.
Enable the `legacy-functions` feature if you require the ability to call older
functions.
## MSRV
The Minimum Supported Rust Version is currently 1.60.0. I will not go out of my
way to avoid bumping this.
## Cargo Features
The `serde` feature can be toggled on in order to `#[derive(Serialize, Deserialize)]`
for every NVML data structure.
#### License
Licensed under either of Apache License, Version
2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
be dual licensed as above, without any additional terms or conditions.
[nvml]: https://developer.nvidia.com/nvidia-management-library-nvml
[libloading]: https://github.com/nagisa/rust_libloading
[once_cell]: https://docs.rs/once_cell/latest/once_cell/sync/struct.Lazy.html
nvml-wrapper-0.11.0/examples/basic_usage.rs 0000644 0000000 0000000 00000006502 10461020230 0016771 0 ustar 0000000 0000000 use nvml_wrapper::enum_wrappers::device::{Clock, TemperatureSensor};
use nvml_wrapper::error::NvmlError;
use nvml_wrapper::{cuda_driver_version_major, cuda_driver_version_minor, Nvml};
use pretty_bytes::converter::convert;
fn main() -> Result<(), NvmlError> {
let nvml = Nvml::init()?;
let cuda_version = nvml.sys_cuda_driver_version()?;
// Grabbing the first device in the system, whichever one that is.
// If you want to ensure you get the same physical device across reboots,
// get devices via UUID or PCI bus IDs.
let device = nvml.device_by_index(0)?;
// Now we can do whatever we want, like getting some data...
let name = device.name()?;
let temperature = device.temperature(TemperatureSensor::Gpu)?;
let mem_info = device.memory_info()?;
let graphics_clock = device.clock_info(Clock::Graphics)?;
let mem_clock = device.clock_info(Clock::Memory)?;
let link_gen = device.current_pcie_link_gen()?;
let link_speed = device
.pcie_link_speed()
.map(u64::from)
// Convert megabytes to bytes
.map(|x| x * 1000000)?;
let link_width = device.current_pcie_link_width()?;
let max_link_gen = device.max_pcie_link_gen()?;
let max_link_width = device.max_pcie_link_width()?;
let max_link_speed = device
.max_pcie_link_speed()?
.as_integer()
.map(u64::from)
// Convert megabytes to bytes
.map(|x| x * 1000000);
let cuda_cores = device.num_cores()?;
let architecture = device.architecture()?;
// And we can use that data (here we just print it)
print!("\n\n");
println!(
"Your {name} (architecture: {architecture}, CUDA cores: {cuda_cores}) \
is currently sitting at {temperature} °C with a graphics clock of \
{graphics_clock} MHz and a memory clock of {mem_clock} MHz. Memory \
usage is {used_mem} out of an available {total_mem}. Right now the \
device is connected via a PCIe gen {link_gen} x{link_width} interface \
with a transfer rate of {link_speed} per lane; the max your hardware \
supports is PCIe gen {max_link_gen} x{max_link_width} at a transfer \
rate of {max_link_speed} per lane.",
name = name,
temperature = temperature,
graphics_clock = graphics_clock,
mem_clock = mem_clock,
used_mem = convert(mem_info.used as _),
total_mem = convert(mem_info.total as _),
link_gen = link_gen,
// Convert byte output to transfers/sec
link_speed = convert(link_speed as _).replace("B", "T") + "/s",
link_width = link_width,
max_link_gen = max_link_gen,
max_link_width = max_link_width,
cuda_cores = cuda_cores,
architecture = architecture,
max_link_speed = max_link_speed
// Convert byte output to transfers/sec
.map(|x| convert(x as _).replace("B", "T") + "/s")
.unwrap_or_else(|| "".into()),
);
println!();
if device.is_multi_gpu_board()? {
println!("This device is on a multi-GPU board.")
} else {
println!("This device is not on a multi-GPU board.")
}
println!();
println!(
"System CUDA version: {}.{}",
cuda_driver_version_major(cuda_version),
cuda_driver_version_minor(cuda_version)
);
print!("\n\n");
Ok(())
}
nvml-wrapper-0.11.0/examples/event_loop.rs 0000644 0000000 0000000 00000003751 10461020230 0016701 0 ustar 0000000 0000000 #[cfg(target_os = "linux")]
fn main() -> Result<(), nvml_wrapper::error::NvmlErrorWithSource> {
use nvml_wrapper::error::NvmlError;
use nvml_wrapper::Nvml;
// Bringing this in allows us to use `Nvml.create_event_loop()`
use nvml_wrapper::high_level::EventLoopProvider;
// Bringing these in for brevity (Event::SomeEvent vs. SomeEvent)
use nvml_wrapper::high_level::Event::*;
let nvml = Nvml::init()?;
let device = nvml.device_by_index(0)?;
// Create an event loop, registering the single device we obtained above
let mut event_loop = nvml.create_event_loop(vec![&device])?;
// Start handling events
event_loop.run_forever(|event, state| match event {
// If there were no errors, extract the event
Ok(event) => match event {
ClockChange(device) => {
if let Ok(uuid) = device.uuid() {
println!("ClockChange event for device with UUID {:?}", uuid);
} else {
// Your error-handling strategy here
}
}
PowerStateChange(device) => {
if let Ok(uuid) = device.uuid() {
println!("PowerStateChange event for device with UUID {:?}", uuid);
} else {
// Your error-handling strategy here
}
}
_ => println!("A different event occurred: {:?}", event),
},
// If there was an error, handle it
Err(e) => match e {
// If the error is `Unknown`, continue looping and hope for the best
NvmlError::Unknown => {}
// The other errors that can occur are almost guaranteed to mean that
// further looping will never be successful (`GpuLost` and
// `Uninitialized`), so we stop looping
_ => state.interrupt(),
},
});
Ok(())
}
#[cfg(not(target_os = "linux"))]
fn main() {
println!("NVML only supports events on linux :(");
}
nvml-wrapper-0.11.0/src/bitmasks/device.rs 0000644 0000000 0000000 00000010506 10461020230 0016550 0 ustar 0000000 0000000 #![allow(deprecated)]
use crate::ffi::bindings::*;
use bitflags::bitflags;
#[cfg(feature = "serde")]
use serde_derive::{Deserialize, Serialize};
bitflags! {
/// Flags used to specify why a GPU is throttling.
// Checked against local
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct ThrottleReasons: u64 {
/// Nothing is running on the GPU.
///
/// This limiter may be removed in a future release.
const GPU_IDLE = nvmlClocksThrottleReasonGpuIdle as u64;
/// GPU clocks are limited by the current applications clocks setting.
const APPLICATIONS_CLOCKS_SETTING = nvmlClocksThrottleReasonApplicationsClocksSetting as u64;
#[deprecated(note = "Renamed to `APPLICATIONS_CLOCKS_SETTING`.")]
const USER_DEFINED_CLOCKS = nvmlClocksThrottleReasonUserDefinedClocks as u64;
/// Software power scaling algorithm is reducing clocks.
const SW_POWER_CAP = nvmlClocksThrottleReasonSwPowerCap as u64;
/**
Hardware slowdown (reducing the core clocks by a factor of 2 or more)
is engaged.
This is an indicator of:
* Temperature being too high
* External Power Brake Asseration being triggered (e.g. by the system power supply)
* Power draw being too high and Fast Trigger protection reducing the clocks
This may also be reported during powerstate or clock change, behavior that may be
removed in a later release.
*/
const HW_SLOWDOWN = nvmlClocksThrottleReasonHwSlowdown as u64;
/**
This GPU is being throttled by another GPU in its sync boost group.
Sync boost groups can be used to maximize performance per watt. All GPUs
in a sync boost group will boost to the minimum possible clocks across
the entire group. Look at the throttle reasons for other GPUs in the
system to find out why this GPU is being held at lower clocks.
*/
const SYNC_BOOST = nvmlClocksThrottleReasonSyncBoost as u64;
/**
Software thermal slowdown.
This is an indicator of one or more of the following:
* The current GPU temperature is above the max GPU operating temperature
* The current memory temperature is above the max memory operating temperature
*/
const SW_THERMAL_SLOWDOWN = nvmlClocksThrottleReasonSwThermalSlowdown as u64;
/**
Hardware thermal slowdown is engaged, reducing core clocks by 2x or more.
This indicates that the temperature of the GPU is too high.
*/
const HW_THERMAL_SLOWDOWN = nvmlClocksThrottleReasonHwThermalSlowdown as u64;
/**
Hardware power brake slowdown is engaged, reducing core clocks by 2x or more.
This indicates that an external power brake assertion is being triggered,
such as by the system power supply.
*/
const HW_POWER_BRAKE_SLOWDOWN = nvmlClocksThrottleReasonHwPowerBrakeSlowdown as u64;
/// GPU clocks are limited by the current setting of display clocks.
const DISPLAY_CLOCK_SETTING = nvmlClocksThrottleReasonDisplayClockSetting as u64;
/// Clocks are as high as possible and are not being throttled.
const NONE = nvmlClocksThrottleReasonNone as u64;
}
}
bitflags! {
/// Flags that specify info about a frame capture session
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct FbcFlags: u32 {
const DIFFMAP_ENABLED = NVML_NVFBC_SESSION_FLAG_DIFFMAP_ENABLED;
const CLASSIFICATIONMAP_ENABLED = NVML_NVFBC_SESSION_FLAG_CLASSIFICATIONMAP_ENABLED;
/// Specifies if capture was requested as a non-blocking call.
const CAPTURE_WITH_WAIT_NO_WAIT = NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_NO_WAIT;
/// Specifies if capture was requested as a blocking call.
const CAPTURE_WITH_WAIT_INFINITE = NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_INFINITE;
/// Specifies if capture was requested as a blocking call with a timeout.
const CAPTURE_WITH_WAIT_TIMEOUT = NVML_NVFBC_SESSION_FLAG_CAPTURE_WITH_WAIT_TIMEOUT;
}
}
nvml-wrapper-0.11.0/src/bitmasks/event.rs 0000644 0000000 0000000 00000003432 10461020230 0016432 0 ustar 0000000 0000000 use crate::ffi::bindings::*;
use bitflags::bitflags;
#[cfg(feature = "serde")]
use serde_derive::{Deserialize, Serialize};
bitflags! {
/**
Event types that you can request to be notified about.
Types can be combined with the Bitwise Or operator `|` when passed to
`Device.register_events()`.
*/
// Checked against local
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct EventTypes: u64 {
/// A corrected texture memory error is not an ECC error, so it does not
/// generate a single bit event.
const SINGLE_BIT_ECC_ERROR = nvmlEventTypeSingleBitEccError as u64;
/// An uncorrected texture memory error is not an ECC error, so it does not
/// generate a double bit event.
const DOUBLE_BIT_ECC_ERROR = nvmlEventTypeDoubleBitEccError as u64;
/**
Power state change event.
On the Fermi architecture, a PState change is an indicator that the GPU
is throttling down due to no work being executed on the GPU, power
capping, or thermal capping. In a typical situation, Fermi-based
GPUs should stay in performance state zero for the duration of the
execution of a compute process.
*/
const PSTATE_CHANGE = nvmlEventTypePState as u64;
const CRITICAL_XID_ERROR = nvmlEventTypeXidCriticalError as u64;
/// Only supports the Kepler architecture.
const CLOCK_CHANGE = nvmlEventTypeClock as u64;
/// Power source change event (battery vs. AC power).
const POWER_SOURCE_CHANGE = nvmlEventTypePowerSourceChange as u64;
/// MIG configuration changes.
const MIG_CONFIG_CHANGE = nvmlEventMigConfigChange as u64;
}
}
nvml-wrapper-0.11.0/src/bitmasks/mod.rs 0000644 0000000 0000000 00000001662 10461020230 0016073 0 ustar 0000000 0000000 pub mod device;
pub mod event;
pub mod nv_link;
use crate::ffi::bindings::*;
use bitflags::bitflags;
#[cfg(feature = "serde")]
use serde_derive::{Deserialize, Serialize};
bitflags! {
/// Generic flags used to specify the default behavior of some functions.
// Checked against local
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Behavior: u32 {
const DEFAULT = nvmlFlagDefault;
const FORCE = nvmlFlagForce;
}
}
bitflags! {
/// Flags that can be passed to `Nvml::init_with_flags()`.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
pub struct InitFlags: u32 {
/// Don't fail to initialize when no NVIDIA GPUs are found.
const NO_GPUS = NVML_INIT_FLAG_NO_GPUS;
/// Don't attach GPUs during initialization.
const NO_ATTACH = NVML_INIT_FLAG_NO_ATTACH;
}
}
nvml-wrapper-0.11.0/src/bitmasks/nv_link.rs 0000644 0000000 0000000 00000003044 10461020230 0016750 0 ustar 0000000 0000000 use crate::ffi::bindings::*;
use bitflags::bitflags;
#[cfg(feature = "serde")]
use serde_derive::{Deserialize, Serialize};
bitflags! {
/**
Represents the NvLink utilization counter packet types that can be counted.
Only applicable when `UtilizationCountUnit`s are packets or bytes. All
packet filter descriptions are target GPU centric.
*/
// Checked against local
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct PacketTypes: u32 {
const NO_OP = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_NOP;
const READ = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_READ;
const WRITE = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_WRITE;
/// Reduction atomic requests.
const RATOM = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_RATOM;
/// Non-reduction atomic requests.
const NON_RATOM = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_NRATOM;
/// Flush requests.
const FLUSH = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_FLUSH;
/// Responses with data.
const WITH_DATA = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_RESPDATA;
/// Responses without data.
const NO_DATA = nvmlNvLinkUtilizationCountPktTypes_enum_NVML_NVLINK_COUNTER_PKTFILTER_RESPNODATA;
}
}
nvml-wrapper-0.11.0/src/device.rs 0000644 0000000 0000000 00000726240 10461020230 0014744 0 ustar 0000000 0000000 #[cfg(target_os = "linux")]
use crate::EventSet;
use crate::NvLink;
use crate::Nvml;
use crate::bitmasks::device::ThrottleReasons;
#[cfg(target_os = "linux")]
use crate::bitmasks::event::EventTypes;
#[cfg(target_os = "windows")]
use crate::bitmasks::Behavior;
use crate::enum_wrappers::{bool_from_state, device::*, state_from_bool};
use crate::enums::device::{
BusType, DeviceArchitecture, FanControlPolicy, GpuLockedClocksSetting, PcieLinkMaxSpeed,
PowerSource,
};
#[cfg(target_os = "linux")]
use crate::error::NvmlErrorWithSource;
use crate::error::{nvml_sym, nvml_try, Bits, NvmlError};
use crate::ffi::bindings::*;
use crate::struct_wrappers::device::*;
use crate::structs::device::*;
#[cfg(target_os = "linux")]
use std::convert::TryInto;
#[cfg(target_os = "linux")]
use std::os::raw::c_ulong;
use std::{
convert::TryFrom,
ffi::CStr,
mem,
os::raw::{c_int, c_uint, c_ulonglong},
ptr,
};
use static_assertions::assert_impl_all;
/**
Struct that represents a device on the system.
Obtain a `Device` with the various methods available to you on the `Nvml`
struct.
Lifetimes are used to enforce that each `Device` instance cannot be used after
the `Nvml` instance it was obtained from is dropped:
```compile_fail
use nvml_wrapper::Nvml;
# use nvml_wrapper::error::*;
# fn main() -> Result<(), NvmlError> {
let nvml = Nvml::init()?;
let device = nvml.device_by_index(0)?;
drop(nvml);
// This won't compile
device.fan_speed(0)?;
# Ok(())
# }
```
This means you shouldn't have to worry about calls to `Device` methods returning
`Uninitialized` errors.
*/
#[derive(Debug)]
pub struct Device<'nvml> {
device: nvmlDevice_t,
nvml: &'nvml Nvml,
}
unsafe impl Send for Device<'_> {}
unsafe impl Sync for Device<'_> {}
assert_impl_all!(Device: Send, Sync);
impl<'nvml> Device<'nvml> {
/**
Create a new `Device` wrapper.
You will most likely never need to call this; see the methods available to you
on the `Nvml` struct to get one.
# Safety
It is your responsibility to ensure that the given `nvmlDevice_t` pointer
is valid.
*/
// Clippy bug, see https://github.com/rust-lang/rust-clippy/issues/5593
#[allow(clippy::missing_safety_doc)]
pub unsafe fn new(device: nvmlDevice_t, nvml: &'nvml Nvml) -> Self {
Self { device, nvml }
}
/// Access the `Nvml` reference this struct wraps
pub fn nvml(&self) -> &'nvml Nvml {
self.nvml
}
/// Get the raw device handle contained in this struct
///
/// Sometimes necessary for C interop.
///
/// # Safety
///
/// This is unsafe to prevent it from being used without care.
pub unsafe fn handle(&self) -> nvmlDevice_t {
self.device
}
/**
Clear all affinity bindings for the calling thread.
Note that this was changed as of version 8.0; older versions cleared affinity for
the calling process and all children.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
# Platform Support
Only supports Linux.
*/
// Checked against local
// Tested (no-run)
#[cfg(target_os = "linux")]
#[doc(alias = "nvmlDeviceClearCpuAffinity")]
pub fn clear_cpu_affinity(&mut self) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceClearCpuAffinity.as_ref())?;
unsafe { nvml_try(sym(self.device)) }
}
/**
Gets the root/admin permissions for the target API.
Only root users are able to call functions belonging to restricted APIs. See
the documentation for the `RestrictedApi` enum for a list of those functions.
Non-root users can be granted access to these APIs through use of
`.set_api_restricted()`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or the apiType is invalid (may occur if
* the C lib changes dramatically?)
* `NotSupported`, if this query is not supported by this `Device` or this `Device`
* does not support the feature that is being queried (e.g. enabling/disabling auto
* boosted clocks is not supported by this `Device`).
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all _fully supported_ products.
*/
// Checked against local
// Tested (except for AutoBoostedClocks)
#[doc(alias = "nvmlDeviceGetAPIRestriction")]
pub fn is_api_restricted(&self, api: Api) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetAPIRestriction.as_ref())?;
unsafe {
let mut restricted_state: nvmlEnableState_t = mem::zeroed();
nvml_try(sym(self.device, api.as_c(), &mut restricted_state))?;
bool_from_state(restricted_state)
}
}
/**
Gets the current clock setting that all applications will use unless an overspec
situation occurs.
This setting can be changed using `.set_applications_clocks()`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or the clockType is invalid (may occur
* if the C lib changes dramatically?)
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetApplicationsClock")]
pub fn applications_clock(&self, clock_type: Clock) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetApplicationsClock.as_ref())?;
unsafe {
let mut clock: c_uint = mem::zeroed();
nvml_try(sym(self.device, clock_type.as_c(), &mut clock))?;
Ok(clock)
}
}
/**
Gets the current and default state of auto boosted clocks.
Auto boosted clocks are enabled by default on some hardware, allowing the GPU to run
as fast as thermals will allow it to.
On Pascal and newer hardware, auto boosted clocks are controlled through application
clocks. Use `.set_applications_clocks()` and `.reset_applications_clocks()` to control
auto boost behavior.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support auto boosted clocks
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested on machines other than my own
#[doc(alias = "nvmlDeviceGetAutoBoostedClocksEnabled")]
pub fn auto_boosted_clocks_enabled(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetAutoBoostedClocksEnabled.as_ref())?;
unsafe {
let mut is_enabled: nvmlEnableState_t = mem::zeroed();
let mut is_enabled_default: nvmlEnableState_t = mem::zeroed();
nvml_try(sym(self.device, &mut is_enabled, &mut is_enabled_default))?;
Ok(AutoBoostClocksEnabledInfo {
is_enabled: bool_from_state(is_enabled)?,
is_enabled_default: bool_from_state(is_enabled_default)?,
})
}
}
/**
Gets the total, available and used size of BAR1 memory.
BAR1 memory is used to map the FB (device memory) so that it can be directly accessed
by the CPU or by 3rd party devices (peer-to-peer on the PCIe bus).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this query
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetBAR1MemoryInfo")]
pub fn bar1_memory_info(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetBAR1MemoryInfo.as_ref())?;
unsafe {
let mut mem_info: nvmlBAR1Memory_t = mem::zeroed();
nvml_try(sym(self.device, &mut mem_info))?;
Ok(mem_info.into())
}
}
/**
Gets the NUMA nodes physically close to the GPU.
Main goal is to facilitate memory placement optimisations for multi CPU/GPU settings.
Node (set) size needs to be something like ` / (std::mem::size_of::() / 8) + 1`
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this query
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// Checked against local
// Tested
#[cfg(target_os = "linux")]
#[doc(alias = "nvmlDeviceGetMemoryAffinity")]
pub fn memory_affinity(
&self,
size: usize,
scope: nvmlAffinityScope_t,
) -> Result, NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetMemoryAffinity.as_ref())?;
unsafe {
if size == 0 {
return Err(NvmlError::InsufficientSize(Some(1)));
}
let mut affinities: Vec = vec![0; size];
nvml_try(sym(
self.device,
size as c_uint,
affinities.as_mut_ptr(),
scope,
))?;
Ok(affinities)
}
}
/**
Gets the board ID for this `Device`, from 0-N.
Devices with the same boardID indicate GPUs connected to the same PLX. Use in
conjunction with `.is_multi_gpu_board()` to determine if they are on the same
board as well.
The boardID returned is a unique ID for the current config. Uniqueness and
ordering across reboots and system configs is not guaranteed (i.e if a Tesla
K40c returns 0x100 and the two GPUs on a Tesla K10 in the same system return
0x200, it is not guaranteed that they will always return those values. They will,
however, always be different from each other).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetBoardId")]
pub fn board_id(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetBoardId.as_ref())?;
unsafe {
let mut id: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut id))?;
Ok(id)
}
}
/**
Gets the brand of this `Device`.
See the `Brand` enum for documentation of possible values.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, check that error's docs for more info
* `Unknown`, on any unexpected error
*/
// Checked against local nvml.h
// Tested
#[doc(alias = "nvmlDeviceGetBrand")]
pub fn brand(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetBrand.as_ref())?;
unsafe {
let mut brand: nvmlBrandType_t = mem::zeroed();
nvml_try(sym(self.device, &mut brand))?;
Brand::try_from(brand)
}
}
/**
Gets bridge chip information for all bridge chips on the board.
Only applicable to multi-GPU devices.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all _fully supported_ devices.
*/
// Checked against local
// Tested on machines other than my own
#[doc(alias = "nvmlDeviceGetBridgeChipInfo")]
pub fn bridge_chip_info(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetBridgeChipInfo.as_ref())?;
unsafe {
let mut info: nvmlBridgeChipHierarchy_t = mem::zeroed();
nvml_try(sym(self.device, &mut info))?;
BridgeChipHierarchy::try_from(info)
}
}
/**
Gets this `Device`'s current clock speed for the given `Clock` type and `ClockId`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `clock_type` is invalid (shouldn't occur?)
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler and newer fully supported devices.
*/
// Checked against local
// Tested (except for CustomerMaxBoost)
#[doc(alias = "nvmlDeviceGetClock")]
pub fn clock(&self, clock_type: Clock, clock_id: ClockId) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetClock.as_ref())?;
unsafe {
let mut clock: c_uint = mem::zeroed();
nvml_try(sym(
self.device,
clock_type.as_c(),
clock_id.as_c(),
&mut clock,
))?;
Ok(clock)
}
}
/**
Gets this `Device`'s customer-defined maximum boost clock speed for the
given `Clock` type.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `clock_type` is invalid (shouldn't occur?)
* `NotSupported`, if this `Device` or the `clock_type` on this `Device`
* does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Pascal and newer fully supported devices.
*/
// Checked against local
// Tested on machines other than my own
#[doc(alias = "nvmlDeviceGetMaxCustomerBoostClock")]
pub fn max_customer_boost_clock(&self, clock_type: Clock) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetMaxCustomerBoostClock.as_ref())?;
unsafe {
let mut clock: c_uint = mem::zeroed();
nvml_try(sym(self.device, clock_type.as_c(), &mut clock))?;
Ok(clock)
}
}
/**
Gets the current compute mode for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, check that error's docs for more info
* `Unknown`, on any unexpected error
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetComputeMode")]
pub fn compute_mode(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetComputeMode.as_ref())?;
unsafe {
let mut mode: nvmlComputeMode_t = mem::zeroed();
nvml_try(sym(self.device, &mut mode))?;
ComputeMode::try_from(mode)
}
}
/**
Gets the CUDA compute capability of this `Device`.
The returned version numbers are the same as those returned by
`cuDeviceGetAttribute()` from the CUDA API.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetCudaComputeCapability")]
pub fn cuda_compute_capability(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetCudaComputeCapability.as_ref())?;
unsafe {
let mut major: c_int = mem::zeroed();
let mut minor: c_int = mem::zeroed();
nvml_try(sym(self.device, &mut major, &mut minor))?;
Ok(CudaComputeCapability { major, minor })
}
}
/**
Gets this `Device`'s current clock speed for the given `Clock` type.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` cannot report the specified clock
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetClockInfo")]
pub fn clock_info(&self, clock_type: Clock) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetClockInfo.as_ref())?;
unsafe {
let mut clock: c_uint = mem::zeroed();
nvml_try(sym(self.device, clock_type.as_c(), &mut clock))?;
Ok(clock)
}
}
/**
Gets information about processes with a compute context running on this `Device`.
This only returns information about running compute processes (such as a CUDA application
with an active context). Graphics applications (OpenGL, DirectX) won't be listed by this
function.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// Tested
#[doc(alias = "nvmlDeviceGetComputeRunningProcesses_v3")]
pub fn running_compute_processes(&self) -> Result, NvmlError> {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetComputeRunningProcesses_v3
.as_ref(),
)?;
unsafe {
let mut count: c_uint = match self.running_compute_processes_count()? {
0 => return Ok(vec![]),
value => value,
};
// Add a bit of headroom in case more processes are launched in
// between the above call to get the expected count and the time we
// actually make the call to get data below.
count += 5;
let mut processes: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, processes.as_mut_ptr()))?;
processes.truncate(count as usize);
Ok(processes.into_iter().map(ProcessInfo::from).collect())
}
}
/**
Gets the number of processes with a compute context running on this `Device`.
This only returns the count of running compute processes (such as a CUDA application
with an active context). Graphics applications (OpenGL, DirectX) won't be counted by this
function.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// Tested as part of `.running_compute_processes()`
#[doc(alias = "nvmlDeviceGetComputeRunningProcesses_v3")]
pub fn running_compute_processes_count(&self) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetComputeRunningProcesses_v3
.as_ref(),
)?;
unsafe {
// Indicates that we want the count
let mut count: c_uint = 0;
// Passing null doesn't mean we want the count, it's just allowed
match sym(self.device, &mut count, ptr::null_mut()) {
nvmlReturn_enum_NVML_ERROR_INSUFFICIENT_SIZE => Ok(count),
// If success, return 0; otherwise, return error
other => nvml_try(other).map(|_| 0),
}
}
}
/**
Gets information about processes with a compute context running on this `Device`.
This only returns information about running compute processes (such as a CUDA application
with an active context). Graphics applications (OpenGL, DirectX) won't be listed by this
function.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetComputeRunningProcesses_v2")]
#[cfg(feature = "legacy-functions")]
pub fn running_compute_processes_v2(&self) -> Result, NvmlError> {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetComputeRunningProcesses_v2
.as_ref(),
)?;
unsafe {
let mut count: c_uint = match self.running_compute_processes_count_v2()? {
0 => return Ok(vec![]),
value => value,
};
// Add a bit of headroom in case more processes are launched in
// between the above call to get the expected count and the time we
// actually make the call to get data below.
count += 5;
let mut processes: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, processes.as_mut_ptr()))?;
processes.truncate(count as usize);
Ok(processes.into_iter().map(ProcessInfo::from).collect())
}
}
/**
Gets the number of processes with a compute context running on this `Device`.
This only returns the count of running compute processes (such as a CUDA application
with an active context). Graphics applications (OpenGL, DirectX) won't be counted by this
function.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetComputeRunningProcesses_v2")]
#[cfg(feature = "legacy-functions")]
pub fn running_compute_processes_count_v2(&self) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetComputeRunningProcesses_v2
.as_ref(),
)?;
unsafe {
// Indicates that we want the count
let mut count: c_uint = 0;
// Passing null doesn't mean we want the count, it's just allowed
match sym(self.device, &mut count, ptr::null_mut()) {
nvmlReturn_enum_NVML_ERROR_INSUFFICIENT_SIZE => Ok(count),
// If success, return 0; otherwise, return error
other => nvml_try(other).map(|_| 0),
}
}
}
/**
Gets a vector of bitmasks with the ideal CPU affinity for this `Device`.
The results are sized to `size`. For example, if processors 0, 1, 32, and 33 are
ideal for this `Device` and `size` == 2, result\[0\] = 0x3, result\[1\] = 0x3.
64 CPUs per unsigned long on 64-bit machines, 32 on 32-bit machines.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `InsufficientSize`, if the passed-in `size` is 0 (must be > 0)
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
# Platform Support
Only supports Linux.
*/
// Checked against local
// Tested
// TODO: Should we trim zeros here or leave it to the caller?
#[cfg(target_os = "linux")]
#[doc(alias = "nvmlDeviceGetCpuAffinity")]
pub fn cpu_affinity(&self, size: usize) -> Result, NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetCpuAffinity.as_ref())?;
unsafe {
if size == 0 {
// Return an error containing the minimum size that can be passed.
return Err(NvmlError::InsufficientSize(Some(1)));
}
let mut affinities: Vec = vec![mem::zeroed(); size];
nvml_try(sym(self.device, size as c_uint, affinities.as_mut_ptr()))?;
Ok(affinities)
}
}
/**
Checks simultaneously if confidential compute is enabled, if the device is in a production environment,
and if the device is accepting client requests.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `NotSupported`, if this query is not supported by the device
* `InvalidArg`, if confidential compute state is invalid
*/
pub fn check_confidential_compute_status(&self) -> Result {
let cc_state_sym = nvml_sym(self.nvml.lib.nvmlSystemGetConfComputeState.as_ref())?;
let cc_gpus_ready_sym = nvml_sym(
self.nvml
.lib
.nvmlSystemGetConfComputeGpusReadyState
.as_ref(),
)?;
unsafe {
let mut state: nvmlConfComputeSystemState_t = mem::zeroed();
nvml_try(cc_state_sym(&mut state))?;
let is_cc_enabled = state.ccFeature == NVML_CC_SYSTEM_FEATURE_ENABLED;
let is_prod_environment = state.environment == NVML_CC_SYSTEM_ENVIRONMENT_PROD;
let mut cc_gpus_ready: std::os::raw::c_uint = 0;
nvml_try(cc_gpus_ready_sym(&mut cc_gpus_ready))?;
let is_accepting_client_requests =
cc_gpus_ready == NVML_CC_ACCEPTING_CLIENT_REQUESTS_TRUE;
Ok(is_cc_enabled && is_prod_environment && is_accepting_client_requests)
}
}
/**
Gets the confidential compute state for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or memory is NULL
* `NotSupported`, if this query is not supported by the device
*/
#[doc(alias = "nvmlDeviceGetConfComputeGpusReadyState")]
pub fn get_confidential_compute_state(&self) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlSystemGetConfComputeGpusReadyState
.as_ref(),
)?;
unsafe {
let mut is_accepting_work: u32 = 0;
nvml_try(sym(&mut is_accepting_work))?;
Ok(is_accepting_work == NVML_CC_ACCEPTING_CLIENT_REQUESTS_TRUE)
}
}
/**
Sets the confidential compute state for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or memory is NULL
* `NotSupported`, if this query is not supported by the device
*/
#[doc(alias = "nvmlDeviceSetConfComputeState")]
pub fn set_confidential_compute_state(&self, is_accepting_work: bool) -> Result<(), NvmlError> {
let sym = nvml_sym(
self.nvml
.lib
.nvmlSystemSetConfComputeGpusReadyState
.as_ref(),
)?;
unsafe {
nvml_try(sym(is_accepting_work as u32))?;
Ok(())
}
}
/**
Gets the confidential compute state for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or counters is NULL
* `NotSupported`, if the device does not support this feature
* `GpuLost`, if the target GPU has fallen off the bus or is otherwise inaccessible
* `ArgumentVersionMismatch`, if the provided version is invalid/unsupported
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceSetConfComputeSettings")]
pub fn is_cc_enabled(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlSystemGetConfComputeSettings.as_ref())?;
unsafe {
let mut settings: nvmlSystemConfComputeSettings_t = mem::zeroed();
nvml_try(sym(&mut settings))?;
Ok(settings.ccFeature == NVML_CC_SYSTEM_FEATURE_ENABLED)
}
}
/**
Gets the confidential compute state for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or counters is NULL
* `NotSupported`, if the device does not support this feature
* `GpuLost`, if the target GPU has fallen off the bus or is otherwise inaccessible
* `ArgumentVersionMismatch`, if the provided version is invalid/unsupported
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlSystemGetConfComputeSettings")]
pub fn is_multi_gpu_protected_pcie_enabled(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlSystemGetConfComputeSettings.as_ref())?;
unsafe {
let mut settings: nvmlSystemConfComputeSettings_t = mem::zeroed();
nvml_try(sym(&mut settings))?;
Ok(settings.multiGpuMode == NVML_CC_SYSTEM_MULTIGPU_PROTECTED_PCIE)
}
}
/**
Gets the confidential compute state for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or counters is NULL
* `NotSupported`, if the device does not support this feature
* `GpuLost`, if the target GPU has fallen off the bus or is otherwise inaccessible
* `ArgumentVersionMismatch`, if the provided version is invalid/unsupported
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlSystemGetConfComputeSettings")]
pub fn is_cc_dev_mode_enabled(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlSystemGetConfComputeSettings.as_ref())?;
unsafe {
let mut settings: nvmlSystemConfComputeSettings_t = mem::zeroed();
nvml_try(sym(&mut settings))?;
Ok(settings.devToolsMode == NVML_CC_SYSTEM_DEVTOOLS_MODE_ON)
}
}
/**
Gets the confidential compute capabilities for this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or memory is NULL
* `NotSupported`, if this query is not supported by the device
*/
pub fn get_confidential_compute_capabilities(
&self,
) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlSystemGetConfComputeCapabilities.as_ref())?;
unsafe {
let mut capabilities: nvmlConfComputeSystemCaps_t = mem::zeroed();
nvml_try(sym(&mut capabilities))?;
let cpu_caps = match capabilities.cpuCaps {
NVML_CC_SYSTEM_CPU_CAPS_NONE => ConfidentialComputeCpuCapabilities::None,
NVML_CC_SYSTEM_CPU_CAPS_AMD_SEV => ConfidentialComputeCpuCapabilities::AmdSev,
NVML_CC_SYSTEM_CPU_CAPS_INTEL_TDX => ConfidentialComputeCpuCapabilities::IntelTdx,
_ => return Err(NvmlError::Unknown),
};
let gpus_caps = match capabilities.gpusCaps {
NVML_CC_SYSTEM_GPUS_CC_CAPABLE => ConfidentialComputeGpuCapabilities::Capable,
NVML_CC_SYSTEM_GPUS_CC_NOT_CAPABLE => {
ConfidentialComputeGpuCapabilities::NotCapable
}
_ => return Err(NvmlError::Unknown),
};
Ok(ConfidentialComputeCapabilities {
cpu_caps,
gpus_caps,
})
}
}
/**
Fetches the confidential compute attestation report for this [`Device`].
This method retrieves a comprehensive attestation report from the device, which includes:
- A 32-byte nonce
- The attestation report size (as big-endian bytes)
- The attestation report data (up to 8192 bytes)
- A flag indicating if CEC attestation is present (as big-endian bytes)
- The CEC attestation report size (as big-endian bytes)
- The CEC attestation report data (up to 4096 bytes)
The returned vector contains all these components concatenated together in the order listed above.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if device is invalid or memory is NULL
* `NotSupported`, if this query is not supported by the device
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetAttestationReport")]
pub fn confidential_compute_gpu_attestation_report(
&self,
nonce: [u8; NVML_CC_GPU_CEC_NONCE_SIZE as usize],
) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetConfComputeGpuAttestationReport
.as_ref(),
)?;
unsafe {
let mut report: nvmlConfComputeGpuAttestationReport_st = mem::zeroed();
report.nonce = nonce;
nvml_try(sym(self.device, &mut report))?;
let is_cec_attestation_report_present = report.isCecAttestationReportPresent == 1;
Ok(ConfidentialComputeGpuAttestationReport {
attestation_report_size: report.attestationReportSize,
attestation_report: report.attestationReport.to_vec(),
is_cec_attestation_report_present,
cec_attestation_report_size: report.cecAttestationReportSize,
cec_attestation_report: report.cecAttestationReport.to_vec(),
})
}
}
/**
Gets the confidential compute GPU certificate for this `Device`.
# Errors
* `Uninitialized` if the library has not been successfully initialized
* `InvalidArg` if device is invalid or memory is NULL
* `NotSupported` if this query is not supported by the device
* `Unknown` on any unexpected error
*/
pub fn confidential_compute_gpu_certificate(
&self,
) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetConfComputeGpuCertificate
.as_ref(),
)?;
unsafe {
let mut certificate_chain: nvmlConfComputeGpuCertificate_t = mem::zeroed();
nvml_try(sym(self.device, &mut certificate_chain))?;
Ok(ConfidentialComputeGpuCertificate {
cert_chain_size: certificate_chain.certChainSize,
attestation_cert_chain_size: certificate_chain.attestationCertChainSize,
cert_chain: certificate_chain.certChain.to_vec(),
attestation_cert_chain: certificate_chain.attestationCertChain.to_vec(),
})
}
}
/**
Gets the current PCIe link generation.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if PCIe link information is not available
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetCurrPcieLinkGeneration")]
pub fn current_pcie_link_gen(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetCurrPcieLinkGeneration.as_ref())?;
unsafe {
let mut link_gen: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut link_gen))?;
Ok(link_gen)
}
}
/**
Gets the current PCIe link width.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if PCIe link information is not available
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetCurrPcieLinkWidth")]
pub fn current_pcie_link_width(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetCurrPcieLinkWidth.as_ref())?;
unsafe {
let mut link_width: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut link_width))?;
Ok(link_width)
}
}
/**
Gets the current utilization and sampling size (sampling size in μs) for the Decoder.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetDecoderUtilization")]
pub fn decoder_utilization(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDecoderUtilization.as_ref())?;
unsafe {
let mut utilization: c_uint = mem::zeroed();
let mut sampling_period: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut utilization, &mut sampling_period))?;
Ok(UtilizationInfo {
utilization,
sampling_period,
})
}
}
/**
Gets global statistics for active frame buffer capture sessions on this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
// tested
#[doc(alias = "nvmlDeviceGetFBCStats")]
pub fn fbc_stats(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFBCStats.as_ref())?;
unsafe {
let mut fbc_stats: nvmlFBCStats_t = mem::zeroed();
nvml_try(sym(self.device, &mut fbc_stats))?;
Ok(fbc_stats.into())
}
}
/**
Gets information about active frame buffer capture sessions on this `Device`.
Note that information such as the horizontal and vertical resolutions, the
average FPS, and the average latency will be zero if no frames have been
captured since a session was started.
# Errors
* `UnexpectedVariant`, for which you can read the docs for
* `IncorrectBits`, if bits are found in a session's info flags that don't
match the flags in this wrapper
* `Uninitialized`, if the library has not been successfully initialized
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
// tested
#[doc(alias = "nvmlDeviceGetFBCSessions")]
pub fn fbc_sessions_info(&self) -> Result, NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFBCSessions.as_ref())?;
unsafe {
let mut count: c_uint = match self.fbc_session_count()? {
0 => return Ok(vec![]),
value => value,
};
let mut info: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, info.as_mut_ptr()))?;
info.into_iter().map(FbcSessionInfo::try_from).collect()
}
}
/**
Gets the number of active frame buffer capture sessions on this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// tested as part of the above
#[doc(alias = "nvmlDeviceGetFBCSessions")]
pub fn fbc_session_count(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFBCSessions.as_ref())?;
unsafe {
let mut count: c_uint = 0;
nvml_try(sym(self.device, &mut count, ptr::null_mut()))?;
Ok(count)
}
}
/**
Gets GPU device hardware attributes
DeviceAttributes represents compute capabilities, Streaming MultiProcessor
capacity, slices allocated to a given GPU, decoding/encoding supported,
available memory for these GPU operations
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetAttributes_v2")]
pub fn attributes(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetAttributes_v2.as_ref())?;
unsafe {
let mut attrs: nvmlDeviceAttributes_t = mem::zeroed();
nvml_try(sym(self.device, &mut attrs))?;
Ok(attrs.into())
}
}
/**
Gets the default applications clock that this `Device` boots with or defaults to after
`reset_applications_clocks()`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetDefaultApplicationsClock")]
pub fn default_applications_clock(&self, clock_type: Clock) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDefaultApplicationsClock.as_ref())?;
unsafe {
let mut clock: c_uint = mem::zeroed();
nvml_try(sym(self.device, clock_type.as_c(), &mut clock))?;
Ok(clock)
}
}
/// Not documenting this because it's deprecated. Read NVIDIA's docs if you
/// must use it.
#[deprecated(note = "use `Device.memory_error_counter()`")]
#[doc(alias = "nvmlDeviceGetDetailedEccErrors")]
pub fn detailed_ecc_errors(
&self,
error_type: MemoryError,
counter_type: EccCounter,
) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDetailedEccErrors.as_ref())?;
unsafe {
let mut counts: nvmlEccErrorCounts_t = mem::zeroed();
nvml_try(sym(
self.device,
error_type.as_c(),
counter_type.as_c(),
&mut counts,
))?;
Ok(counts.into())
}
}
/**
Gets the display active state for this `Device`.
This method indicates whether a display is initialized on this `Device`.
For example, whether or not an X Server is attached to this device and
has allocated memory for the screen.
A display can be active even when no monitor is physically attached to this `Device`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetDisplayActive")]
pub fn is_display_active(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDisplayActive.as_ref())?;
unsafe {
let mut state: nvmlEnableState_t = mem::zeroed();
nvml_try(sym(self.device, &mut state))?;
bool_from_state(state)
}
}
/**
Gets whether a physical display is currently connected to any of this `Device`'s
connectors.
This calls the C function `nvmlDeviceGetDisplayMode`.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetDisplayMode")]
pub fn is_display_connected(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDisplayMode.as_ref())?;
unsafe {
let mut state: nvmlEnableState_t = mem::zeroed();
nvml_try(sym(self.device, &mut state))?;
bool_from_state(state)
}
}
/**
Gets the current and pending driver model for this `Device`.
On Windows, the device driver can run in either WDDM or WDM (TCC) modes.
If a display is attached to the device it must run in WDDM mode. TCC mode
is preferred if a display is not attached.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if the platform is not Windows
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi and newer fully supported devices.
# Platform Support
Only supports Windows.
*/
// Checked against local
// Tested
#[cfg(target_os = "windows")]
#[doc(alias = "nvmlDeviceGetDriverModel")]
pub fn driver_model(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetDriverModel.as_ref())?;
unsafe {
let mut current: nvmlDriverModel_t = mem::zeroed();
let mut pending: nvmlDriverModel_t = mem::zeroed();
nvml_try(sym(self.device, &mut current, &mut pending))?;
Ok(DriverModelState {
current: DriverModel::try_from(current)?,
pending: DriverModel::try_from(pending)?,
})
}
}
/**
Get the current and pending ECC modes for this `Device`.
Changing ECC modes requires a reboot. The "pending" ECC mode refers to the target
mode following the next reboot.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Fermi and newer fully supported devices. Only applicable to devices with
ECC. Requires `InfoRom::ECC` version 1.0 or higher.
*/
// Checked against local
// Tested on machines other than my own
#[doc(alias = "nvmlDeviceGetEccMode")]
pub fn is_ecc_enabled(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEccMode.as_ref())?;
unsafe {
let mut current: nvmlEnableState_t = mem::zeroed();
let mut pending: nvmlEnableState_t = mem::zeroed();
nvml_try(sym(self.device, &mut current, &mut pending))?;
Ok(EccModeState {
currently_enabled: bool_from_state(current)?,
pending_enabled: bool_from_state(pending)?,
})
}
}
/**
Gets the current utilization and sampling size (sampling size in μs) for the Encoder.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetEncoderUtilization")]
pub fn encoder_utilization(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEncoderUtilization.as_ref())?;
unsafe {
let mut utilization: c_uint = mem::zeroed();
let mut sampling_period: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut utilization, &mut sampling_period))?;
Ok(UtilizationInfo {
utilization,
sampling_period,
})
}
}
/**
Gets the current capacity of this device's encoder in macroblocks per second.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this device is invalid
* `NotSupported`, if this `Device` does not support the given `for_type`
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
// Tested
#[doc(alias = "nvmlDeviceGetEncoderCapacity")]
pub fn encoder_capacity(&self, for_type: EncoderType) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEncoderCapacity.as_ref())?;
unsafe {
let mut capacity: c_uint = mem::zeroed();
nvml_try(sym(self.device, for_type.as_c(), &mut capacity))?;
Ok(capacity)
}
}
/**
Gets the current encoder stats for this device.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this device is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
// Tested
#[doc(alias = "nvmlDeviceGetEncoderStats")]
pub fn encoder_stats(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEncoderStats.as_ref())?;
unsafe {
let mut session_count: c_uint = mem::zeroed();
let mut average_fps: c_uint = mem::zeroed();
let mut average_latency: c_uint = mem::zeroed();
nvml_try(sym(
self.device,
&mut session_count,
&mut average_fps,
&mut average_latency,
))?;
Ok(EncoderStats {
session_count,
average_fps,
average_latency,
})
}
}
/**
Gets information about active encoder sessions on this device.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, if an enum variant not defined in this wrapper gets
* returned in a field of an `EncoderSessionInfo` struct
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
// Tested
// TODO: Test this with an active session and make sure it works
#[doc(alias = "nvmlDeviceGetEncoderSessions")]
pub fn encoder_sessions(&self) -> Result, NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEncoderSessions.as_ref())?;
unsafe {
let mut count = match self.encoder_sessions_count()? {
0 => return Ok(vec![]),
value => value,
};
let mut sessions: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, sessions.as_mut_ptr()))?;
sessions.truncate(count as usize);
sessions
.into_iter()
.map(EncoderSessionInfo::try_from)
.collect::>()
}
}
/**
Gets the number of active encoder sessions on this device.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// tested as part of the above
fn encoder_sessions_count(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEncoderSessions.as_ref())?;
unsafe {
let mut count: c_uint = 0;
nvml_try(sym(self.device, &mut count, ptr::null_mut()))?;
Ok(count)
}
}
/**
Gets the effective power limit in milliwatts that the driver enforces after taking
into account all limiters.
Note: This can be different from the `.power_management_limit()` if other limits
are set elswhere. This includes the out-of-band power limit interface.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Kepler or newer fully supported devices.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetEnforcedPowerLimit")]
pub fn enforced_power_limit(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetEnforcedPowerLimit.as_ref())?;
unsafe {
let mut limit: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut limit))?;
Ok(limit)
}
}
/**
Gets the GPU clock frequency offset value.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with unlocked overclocking capabilities.
*/
// Checked against local
// Tested (no-run)
#[doc(alias = "nvmlDeviceGetGpcClkVfOffset")]
pub fn gpc_clock_vf_offset(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetGpcClkVfOffset.as_ref())?;
unsafe {
let mut offset: c_int = mem::zeroed();
nvml_try(sym(self.device, &mut offset))?;
Ok(offset)
}
}
/**
Sets the GPU clock frequency offset value.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with unlocked overclocking capabilities.
*/
// Checked against local
// Tested (no-run)
#[doc(alias = "nvmlDeviceGetGpcClkVfOffset")]
pub fn set_gpc_clock_vf_offset(&self, offset: i32) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceSetGpcClkVfOffset.as_ref())?;
unsafe { nvml_try(sym(self.device, offset)) }
}
/**
Gets the memory clock frequency offset value.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with unlocked overclocking capabilities.
*/
// Checked against local
// Tested (no-run)
#[doc(alias = "nvmlDeviceGetGpcMemClkVfOffset")]
pub fn mem_clock_vf_offset(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetMemClkVfOffset.as_ref())?;
unsafe {
let mut offset: c_int = mem::zeroed();
nvml_try(sym(self.device, &mut offset))?;
Ok(offset)
}
}
/**
Sets the memory clock frequency offset value.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with unlocked overclocking capabilities.
*/
// Checked against local
// Tested (no-run)
#[doc(alias = "nvmlDeviceSetGpcMemClkVfOffset")]
pub fn set_mem_clock_vf_offset(&self, offset: i32) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceSetMemClkVfOffset.as_ref())?;
unsafe { nvml_try(sym(self.device, offset)) }
}
/**
Gets the intended operating speed of the specified fan as a percentage of the
maximum fan speed (100%).
Note: The reported speed is the intended fan speed. If the fan is physically blocked
and unable to spin, the output will not match the actual fan speed.
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan or is newer than Maxwell
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with dedicated fans.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetFanSpeed_v2")]
pub fn fan_speed(&self, fan_idx: u32) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFanSpeed_v2.as_ref())?;
unsafe {
let mut speed: c_uint = mem::zeroed();
nvml_try(sym(self.device, fan_idx, &mut speed))?;
Ok(speed)
}
}
/**
Retrieves the intended operating speed in rotations per minute (RPM) of the
device's specified fan.
Note: The reported speed is the intended fan speed. If the fan is physically
blocked and unable to spin, the output will not match the actual fan speed.
...
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan or is newer than Maxwell
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
For Maxwell or newer fully supported devices.
For all discrete products with dedicated fans.
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetFanSpeedRPM")]
pub fn fan_speed_rpm(&self, fan_idx: u32) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFanSpeedRPM.as_ref())?;
unsafe {
let mut fan_speed: nvmlFanSpeedInfo_t = mem::zeroed();
// Implements NVML_STRUCT_VERSION(FanSpeedInfo, 1), as detailed in nvml.h
fan_speed.version =
(std::mem::size_of::() | (1_usize << 24_usize)) as u32;
fan_speed.fan = fan_idx;
nvml_try(sym(self.device, &mut fan_speed))?;
Ok(fan_speed.speed)
}
}
/**
Retrieves the min and max fan speed that user can set for the GPU fan.
Returns a (min, max) tuple.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not have fans
* `Unknown`, on any unexpected error
# Device Support
For all cuda-capable discrete products with fans
*/
// Checked against local
// Tested
#[doc(alias = "nvmlDeviceGetMinMaxFanSpeed")]
pub fn min_max_fan_speed(&self) -> Result<(u32, u32), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetMinMaxFanSpeed.as_ref())?;
unsafe {
let mut min = mem::zeroed();
let mut max = mem::zeroed();
nvml_try(sym(self.device, &mut min, &mut max))?;
Ok((min, max))
}
}
/**
Gets current fan control policy.
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported discrete devices with fans.
*/
#[doc(alias = "nvmlGetFanControlPolicy_v2")]
pub fn fan_control_policy(&self, fan_idx: u32) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetFanControlPolicy_v2.as_ref())?;
unsafe {
let mut policy: nvmlFanControlPolicy_t = mem::zeroed();
nvml_try(sym(self.device, fan_idx, &mut policy))?;
FanControlPolicy::try_from(policy)
}
}
/**
Sets fan control policy.
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported discrete devices with fans.
*/
#[doc(alias = "nvmlDeviceSetFanControlPolicy")]
pub fn set_fan_control_policy(
&mut self,
fan_idx: u32,
policy: FanControlPolicy,
) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceSetFanControlPolicy.as_ref())?;
unsafe { nvml_try(sym(self.device, fan_idx, policy.as_c())) }
}
/**
Sets the speed of a specified fan.
WARNING: This function changes the fan control policy to manual. It means that YOU have to monitor the temperature and adjust the fan speed accordingly.
If you set the fan speed too low you can burn your GPU! Use [`Device::set_default_fan_speed`] to restore default control policy.
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported discrete devices with fans.
*/
#[doc(alias = "nvmlDeviceSetFanSpeed_v2")]
pub fn set_fan_speed(&mut self, fan_idx: u32, speed: u32) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceSetFanSpeed_v2.as_ref())?;
unsafe { nvml_try(sym(self.device, fan_idx, speed)) }
}
/**
Sets the the fan control policy to default.
You can determine valid fan indices using [`Self::num_fans()`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid or `fan_idx` is invalid
* `NotSupported`, if this `Device` does not have a fan
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported discrete devices with fans.
*/
#[doc(alias = "nvmlDeviceSetDefaultFanSpeed_v2")]
pub fn set_default_fan_speed(&mut self, fan_idx: u32) -> Result<(), NvmlError> {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceSetDefaultFanSpeed_v2.as_ref())?;
unsafe { nvml_try(sym(self.device, fan_idx)) }
}
/**
Gets the number of fans on this [`Device`].
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `NotSupported`, if this `Device` does not have a fan
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports all discrete products with dedicated fans.
*/
#[doc(alias = "nvmlDeviceGetNumFans")]
pub fn num_fans(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetNumFans.as_ref())?;
unsafe {
let mut count: c_uint = mem::zeroed();
nvml_try(sym(self.device, &mut count))?;
Ok(count)
}
}
/**
Gets the current GPU operation mode and the pending one (that it will switch to
after a reboot).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
# Device Support
Supports GK110 M-class and X-class Tesla products from the Kepler family. Modes `LowDP`
and `AllOn` are supported on fully supported GeForce products. Not supported
on Quadro and Tesla C-class products.
*/
// Checked against local
// Tested on machines other than my own
#[doc(alias = "nvmlDeviceGetGpuOperationMode")]
pub fn gpu_operation_mode(&self) -> Result {
let sym = nvml_sym(self.nvml.lib.nvmlDeviceGetGpuOperationMode.as_ref())?;
unsafe {
let mut current: nvmlGpuOperationMode_t = mem::zeroed();
let mut pending: nvmlGpuOperationMode_t = mem::zeroed();
nvml_try(sym(self.device, &mut current, &mut pending))?;
Ok(OperationModeState {
current: OperationMode::try_from(current)?,
pending: OperationMode::try_from(pending)?,
})
}
}
/**
Gets information about processes with a graphics context running on this `Device`.
This only returns information about graphics based processes (OpenGL, DirectX, etc.).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
// Tested
#[doc(alias = "nvmlDeviceGetGraphicsRunningProcesses_v3")]
pub fn running_graphics_processes(&self) -> Result, NvmlError> {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetGraphicsRunningProcesses_v3
.as_ref(),
)?;
unsafe {
let mut count: c_uint = match self.running_graphics_processes_count()? {
0 => return Ok(vec![]),
value => value,
};
// Add a bit of headroom in case more processes are launched in
// between the above call to get the expected count and the time we
// actually make the call to get data below.
count += 5;
let mut processes: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, processes.as_mut_ptr()))?;
processes.truncate(count as usize);
Ok(processes.into_iter().map(ProcessInfo::from).collect())
}
}
/**
Gets the number of processes with a graphics context running on this `Device`.
This only returns the count of graphics based processes (OpenGL, DirectX).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
*/
// Tested as part of `.running_graphics_processes()`
#[doc(alias = "nvmlDeviceGetGraphicsRunningProcesses_v3")]
pub fn running_graphics_processes_count(&self) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetGraphicsRunningProcesses_v3
.as_ref(),
)?;
unsafe {
// Indicates that we want the count
let mut count: c_uint = 0;
// Passing null doesn't indicate that we want the count. It's just allowed.
match sym(self.device, &mut count, ptr::null_mut()) {
nvmlReturn_enum_NVML_ERROR_INSUFFICIENT_SIZE => Ok(count),
// If success, return 0; otherwise, return error
other => nvml_try(other).map(|_| 0),
}
}
}
/**
Gets information about processes with a graphics context running on this `Device`.
This only returns information about graphics based processes (OpenGL, DirectX, etc.).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetGraphicsRunningProcesses_v2")]
#[cfg(feature = "legacy-functions")]
pub fn running_graphics_processes_v2(&self) -> Result, NvmlError> {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetGraphicsRunningProcesses_v2
.as_ref(),
)?;
unsafe {
let mut count: c_uint = match self.running_graphics_processes_count_v2()? {
0 => return Ok(vec![]),
value => value,
};
// Add a bit of headroom in case more processes are launched in
// between the above call to get the expected count and the time we
// actually make the call to get data below.
count += 5;
let mut processes: Vec = vec![mem::zeroed(); count as usize];
nvml_try(sym(self.device, &mut count, processes.as_mut_ptr()))?;
processes.truncate(count as usize);
Ok(processes.into_iter().map(ProcessInfo::from).collect())
}
}
/**
Gets the number of processes with a graphics context running on this `Device`.
This only returns the count of graphics based processes (OpenGL, DirectX).
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `UnexpectedVariant`, for which you can read the docs for
* `Unknown`, on any unexpected error
*/
#[doc(alias = "nvmlDeviceGetGraphicsRunningProcesses_v2")]
#[cfg(feature = "legacy-functions")]
pub fn running_graphics_processes_count_v2(&self) -> Result {
let sym = nvml_sym(
self.nvml
.lib
.nvmlDeviceGetGraphicsRunningProcesses_v2
.as_ref(),
)?;
unsafe {
// Indicates that we want the count
let mut count: c_uint = 0;
// Passing null doesn't indicate that we want the count. It's just allowed.
match sym(self.device, &mut count, ptr::null_mut()) {
nvmlReturn_enum_NVML_ERROR_INSUFFICIENT_SIZE => Ok(count),
// If success, return 0; otherwise, return error
other => nvml_try(other).map(|_| 0),
}
}
}
/**
Gets utilization stats for relevant currently running processes.
Utilization stats are returned for processes that had a non-zero utilization stat
at some point during the target sample period. Passing `None` as the
`last_seen_timestamp` will target all samples that the driver has buffered; passing
a timestamp retrieved from a previous query will target samples taken since that
timestamp.
# Errors
* `Uninitialized`, if the library has not been successfully initialized
* `InvalidArg`, if this `Device` is invalid
* `NotSupported`, if this `Device` does not support this feature
* `GpuLost`, if this `Device` has fallen off the bus or is otherwise inaccessible
* `Unknown`, on any unexpected error
# Device Support
Supports Maxwell or newer fully supported devices.
*/
#[doc(alias = "nvmlDeviceGetProcessUtilization")]
pub fn process_utilization_stats(
&self,
last_seen_timestamp: T,
) -> Result, NvmlError>
where
T: Into