Merge amd-dev into amd-master 20240515
Signed-off-by: Maisam Arif <maisarif@amd.com>
Change-Id: I64bba263badc1b1dfa8fab5baf90a5f2ad8ea11d
[ROCm/amdsmi commit: b0fc5d2004]
This commit is contained in:
@@ -1,27 +1,30 @@
|
||||
# Change Log for AMD SMI Library
|
||||
# Changelog for AMD SMI Library
|
||||
|
||||
Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/](https://rocm.docs.amd.com/projects/amdsmi/en/latest/).
|
||||
Full documentation for amd_smi_lib is available at [https://rocm.docs.amd.com/projects/amdsmi](https://rocm.docs.amd.com/projects/amdsmi/en/latest/).
|
||||
|
||||
***All information listed below is for reference and subject to change.***
|
||||
|
||||
## amd_smi_lib for ROCm 6.1.2
|
||||
|
||||
### Added
|
||||
### Additions
|
||||
|
||||
- **Added Ring Hang event**
|
||||
- **Added macros that were in `amdsmi.h` to the amdsmi Python library `amdsmi_interface.py`**.
|
||||
Added macros to reference max size limitations for certain amdsmi functions such as max dpm policies and max fanspeed.
|
||||
|
||||
- **Added Ring Hang event**.
|
||||
Added `AMDSMI_EVT_NOTIF_RING_HANG` to the possible events in the `amdsmi_evt_notification_type_t` enum.
|
||||
|
||||
- **Added process isolation and clean shader APIs and CLI commands**
|
||||
- **Added process isolation and clean shader APIs and CLI commands**.
|
||||
Added APIs CLI and APIs to address LeftoverLocals security issues. Allowing clearing the sram data and setting process isolation on a per GPU basis. New APIs:
|
||||
- `amdsmi_get_gpu_process_isolation()`
|
||||
- `amdsmi_set_gpu_process_isolation()`
|
||||
- `amdsmi_set_gpu_clear_sram_data()`
|
||||
|
||||
- **Added `MIN_POWER` to output of `amd-smi static --limit`**
|
||||
This change was to help users to identify what range they can change the power cap of the GPU to. We added this to simplify why a device supports (or does not support) power capping (also known as overdrive). See `amd-smi set -g all --power-cap <value in W>` or `amd-smi reset -g all --power-cap`.
|
||||
- **Added `MIN_POWER` to output of `amd-smi static --limit`**.
|
||||
This change helps users identify the range to which they can change the power cap of the GPU. The change is added to simplify why a device supports (or does not support) power capping (also known as overdrive). See `amd-smi set -g all --power-cap <value in W>` or `amd-smi reset -g all --power-cap`.
|
||||
|
||||
```shell
|
||||
$ amd-smi static --limit
|
||||
$ amd-smi static --limit
|
||||
GPU: 0
|
||||
LIMIT:
|
||||
MAX_POWER: 203 W
|
||||
@@ -47,16 +50,43 @@ GPU: 1
|
||||
SHUTDOWN_VRAM_TEMPERATURE: 105 °C
|
||||
```
|
||||
|
||||
### Changed
|
||||
### Optimizations
|
||||
|
||||
- **`amdsmi_get_power_cap_info` now returns values in uW instead of W**
|
||||
- **Updated `amd-smi monitor --pcie` output**.
|
||||
The source for pcie bandwidth monitor output was a legacy file we no longer support and was causing delays within the monitor command. The output is no longer using TX/RX but instantaneous bandwidth from gpu_metrics instead; updated output:
|
||||
|
||||
```shell
|
||||
$ amd-smi monitor --pcie
|
||||
GPU PCIE_BW
|
||||
0 26 Mb/s
|
||||
```
|
||||
|
||||
- **Updated CLI voltage curve command output**.
|
||||
The output for `amd-smi metric --voltage-curve` now splits the frequency and voltage output by curve point or outputs N/A if not applicable
|
||||
|
||||
```shell
|
||||
GPU: 0
|
||||
VOLTAGE_CURVE:
|
||||
POINT_0_FREQUENCY: 872 Mhz
|
||||
POINT_0_VOLTAGE: 736 mV
|
||||
POINT_1_FREQUENCY: 1354 Mhz
|
||||
POINT_1_VOLTAGE: 860 mV
|
||||
POINT_2_FREQUENCY: 1837 Mhz
|
||||
POINT_2_VOLTAGE: 1186 mV
|
||||
```
|
||||
|
||||
- **Updated `amdsmi_get_gpu_board_info()` now has larger structure sizes for `amdsmi_board_info_t`**.
|
||||
Updated sizes that work for retreiving relavant board information across AMD's
|
||||
ASIC products. This requires users to update any ABIs using this structure.
|
||||
|
||||
- **`amdsmi_get_power_cap_info` now returns values in uW instead of W**.
|
||||
`amdsmi_get_power_cap_info` will return in uW as originally reflected by driver. Previously `amdsmi_get_power_cap_info` returned W values, this conflicts with our sets and modifies values retrieved from driver. We decided to keep the values returned from driver untouched (in original units, uW). Then in CLI we will convert to watts (as previously done - no changes here). Additionally, driver made updates to min power cap displayed for devices when overdrive is disabled which prompted for this change (in this case min_power_cap and max_power_cap are the same).
|
||||
|
||||
- **Updated Python Library return types for amdsmi_get_gpu_memory_reserved_pages & amdsmi_get_gpu_bad_page_info**
|
||||
- **Updated Python Library return types for amdsmi_get_gpu_memory_reserved_pages & amdsmi_get_gpu_bad_page_info**.
|
||||
Previously calls were returning "No bad pages found." if no pages were found, now it only returns the list type and can be empty.
|
||||
|
||||
- **Updated `amd-smi metric --ecc-blocks` output**
|
||||
The ecc blocks arguement was outputing blocks without counters available, updated the filtering show blocks that counters are available for:
|
||||
- **Updated `amd-smi metric --ecc-blocks` output**.
|
||||
The ecc blocks argument was outputing blocks without counters available, updated the filtering show blocks that counters are available for:
|
||||
|
||||
``` shell
|
||||
$ amd-smi metric --ecc-block
|
||||
@@ -92,23 +122,21 @@ GPU: 0
|
||||
DEFERRED_COUNT: 0
|
||||
```
|
||||
|
||||
- **Removed `amdsmi_get_gpu_process_info` from python library**
|
||||
amdsmi_get_gpu_process_info was removed from the C library in an earlier build, but the API was still in the python interface
|
||||
- **Removed `amdsmi_get_gpu_process_info` from Python library**.
|
||||
amdsmi_get_gpu_process_info was removed from the C library in an earlier build, but the API was still in the Python interface.
|
||||
|
||||
### Optimizations
|
||||
### Fixes
|
||||
|
||||
- **Updated `amd-smi monitor --pcie` output**
|
||||
The source for pcie bandwidth monitor output was a legacy file we no longer support and was causing delays within the monitor command. The output is no longer using TX/RX but instantaneous bandwidth from gpu_metrics instead; updated output:
|
||||
- **`amdsmi_get_gpu_board_info()` no longer returns junk char strings**.
|
||||
Previously if there was a partial failure to retrieve character strings, we would return
|
||||
garbage output to users using the API. This fix intends to populate as many values as possible.
|
||||
Then any failure(s) found along the way, `\0` is provided to `amdsmi_board_info_t`
|
||||
structures data members which cannot be populated. Ensuring empty char string values.
|
||||
|
||||
```shell
|
||||
$ amd-smi monitor --pcie
|
||||
GPU PCIE_BW
|
||||
0 26 Mb/s
|
||||
```
|
||||
- **Fixed parsing of `pp_od_clk_voltage` within `amdsmi_get_gpu_od_volt_info`**.
|
||||
The parsing of `pp_od_clk_voltage` was not dynamic enough to work with the dropping of voltage curve support on MI series cards. This propagates down to correcting the CLI's output `amd-smi metric --voltage-curve` to N/A if voltage curve is not enabled.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Fixed `amd-smi metric --power` now provides power output for Navi2x/Navi3x/MI1x**
|
||||
- **Fixed `amd-smi metric --power` now provides power output for Navi2x/Navi3x/MI1x**.
|
||||
These systems use an older version of gpu_metrics in amdgpu. This fix only updates what CLI outputs.
|
||||
No change in any of our APIs.
|
||||
|
||||
@@ -133,11 +161,11 @@ GPU: 1
|
||||
THROTTLE_STATUS: UNTHROTTLED
|
||||
```
|
||||
|
||||
- **Fixed `amdsmitstReadWrite.TestPowerCapReadWrite` test for Navi3X, Navi2X, MI100**
|
||||
- **Fixed `amdsmitstReadWrite.TestPowerCapReadWrite` test for Navi3X, Navi2X, MI100**.
|
||||
Updates required `amdsmi_get_power_cap_info` to return in uW as originally reflected by driver. Previously `amdsmi_get_power_cap_info` returned W values, this conflicts with our sets and modifies values retrieved from driver. We decided to keep the values returned from driver untouched (in original units, uW). Then in CLI we will convert to watts (as previously done - no changes here). Additionally, driver made updates to min power cap displayed for devices when overdrive is disabled which prompted for this change (in this case min_power_cap and max_power_cap are the same).
|
||||
|
||||
- **Fixed python interface call amdsmi_get_gpu_memory_reserved_pages & amdsmi_get_gpu_bad_page_info**
|
||||
Previously python interface calls to populated bad pages resulted in a `ValueError: NULL pointer access`. This fixes the bad-pages subcommand CLI subcommand as well.
|
||||
- **Fixed Python interface call amdsmi_get_gpu_memory_reserved_pages & amdsmi_get_gpu_bad_page_info**.
|
||||
Previously Python interface calls to populated bad pages resulted in a `ValueError: NULL pointer access`. This fixes the bad-pages subcommand CLI subcommand as well.
|
||||
|
||||
### Known Issues
|
||||
|
||||
@@ -145,13 +173,9 @@ Previously python interface calls to populated bad pages resulted in a `ValueErr
|
||||
|
||||
## amd_smi_lib for ROCm 6.1.1
|
||||
|
||||
### Added
|
||||
### Changes
|
||||
|
||||
- N/A
|
||||
|
||||
### Changed
|
||||
|
||||
- **Updated metrics --clocks**
|
||||
- **Updated metrics --clocks**.
|
||||
Output for `amd-smi metric --clock` is updated to reflect each engine and bug fixes for the clock lock status and deep sleep status.
|
||||
|
||||
``` shell
|
||||
@@ -262,7 +286,7 @@ GPU: 0
|
||||
DEEP_SLEEP: ENABLED
|
||||
```
|
||||
|
||||
- **Added deferred ecc counts**
|
||||
- **Added deferred ecc counts**.
|
||||
Added deferred error correctable counts to `amd-smi metric --ecc --ecc-blocks`
|
||||
|
||||
```shell
|
||||
@@ -286,7 +310,7 @@ GPU: 0
|
||||
...
|
||||
```
|
||||
|
||||
- **Updated `amd-smi topology --json` to align with host/guest**
|
||||
- **Updated `amd-smi topology --json` to align with host/guest**.
|
||||
Topology's `--json` output now is changed to align with output host/guest systems. Additionally, users can select/filter specific topology details as desired (refer to `amd-smi topology -h` for full list). See examples shown below.
|
||||
|
||||
*Previous format:*
|
||||
@@ -419,35 +443,31 @@ $ /opt/rocm/bin/amd-smi topology -a -t --json
|
||||
]
|
||||
```
|
||||
|
||||
### Optimizations
|
||||
### Fixes
|
||||
|
||||
- N/A
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Fix for GPU reset error on non-amdgpu cards**
|
||||
- **Fix for GPU reset error on non-amdgpu cards**.
|
||||
Previously our reset could attempting to reset non-amd GPUS- resuting in "Unable to reset non-amd GPU" error. Fix
|
||||
updates CLI to target only AMD ASICs.
|
||||
|
||||
- **Fix for `amd-smi metric --pcie` and `amdsmi_get_pcie_info()`Navi32/31 cards**
|
||||
- **Fix for `amd-smi metric --pcie` and `amdsmi_get_pcie_info()`Navi32/31 cards**.
|
||||
Updated API to include `amdsmi_card_form_factor_t.AMDSMI_CARD_FORM_FACTOR_CEM`. Prevously, this would report "UNKNOWN". This fix
|
||||
provides the correct board `SLOT_TYPE` associated with these ASICs (and other Navi cards).
|
||||
|
||||
- **Fix for `amd-smi process`**
|
||||
- **Fix for `amd-smi process`**.
|
||||
Fixed output results when getting processes running on a device.
|
||||
|
||||
- **Improved Error handling for `amd-smi process`**
|
||||
- **Improved Error handling for `amd-smi process`**.
|
||||
Fixed Attribute Error when getting process in csv format
|
||||
|
||||
### Known issues
|
||||
|
||||
- `amd-smi bad-pages` can results with "ValueError: NULL pointer access" with certain PM FW versions
|
||||
- `amd-smi bad-pages` can results with "ValueError: NULL pointer access" with certain PM FW versions.
|
||||
|
||||
## amd_smi_lib for ROCm 6.1.0
|
||||
|
||||
### Added
|
||||
### Additions
|
||||
|
||||
- **Added Monitor Command**
|
||||
- **Added Monitor Command**.
|
||||
Provides users the ability to customize GPU metrics to capture, collect, and observe. Output is provided in a table view. This aligns closer to ROCm SMI `rocm-smi` (no argument), additionally allows uers to customize what data is helpful for their use-case.
|
||||
|
||||
```shell
|
||||
@@ -507,7 +527,7 @@ GPU POWER GPU_TEMP MEM_TEMP GFX_UTIL GFX_CLOCK MEM_UTIL MEM_CLOCK VRAM_U
|
||||
7 175 W 34 °C 32 °C 0 % 113 MHz 0 % 900 MHz 283 MB 196300 MB
|
||||
```
|
||||
|
||||
- **Integrated ESMI Tool**
|
||||
- **Integrated ESMI Tool**.
|
||||
Users can get CPU metrics and telemetry through our API and CLI tools. This information can be seen in `amd-smi static` and `amd-smi metric` commands. Only available for limited target processors. As of ROCm 6.0.2, this is listed as:
|
||||
- AMD Zen3 based CPU Family 19h Models 0h-Fh and 30h-3Fh
|
||||
- AMD Zen4 based CPU Family 19h Models 10h-1Fh and A0-AFh
|
||||
@@ -657,7 +677,7 @@ CPU: 0
|
||||
RESPONSE: N/A
|
||||
```
|
||||
|
||||
- **Added support for new metrics: VCN, JPEG engines, and PCIe errors**
|
||||
- **Added support for new metrics: VCN, JPEG engines, and PCIe errors**.
|
||||
Using the AMD SMI tool, users can retreive VCN, JPEG engines, and PCIe errors by calling `amd-smi metric -P` or `amd-smi metric --usage`. Depending on device support, `VCN_ACTIVITY` will update for MI3x ASICs (with 4 separate VCN engine activities) for older asics `MM_ACTIVITY` with UVD/VCN engine activity (average of all engines). `JPEG_ACTIVITY` is a new field for MI3x ASICs, where device can support up to 32 JPEG engine activities. See our documentation for more in-depth understanding of these new fields.
|
||||
|
||||
```shell
|
||||
@@ -690,7 +710,7 @@ GPU: 0
|
||||
|
||||
```
|
||||
|
||||
- **Added AMDSMI Tool Version**
|
||||
- **Added AMDSMI Tool Version**.
|
||||
AMD SMI will report ***three versions***: AMDSMI Tool, AMDSMI Library version, and ROCm version.
|
||||
The AMDSMI Tool version is the CLI/tool version number with commit ID appended after `+` sign.
|
||||
The AMDSMI Library version is the library package version number.
|
||||
@@ -701,7 +721,7 @@ $ amd-smi version
|
||||
AMDSMI Tool: 23.4.2+505b858 | AMDSMI Library version: 24.2.0.0 | ROCm version: 6.1.0
|
||||
```
|
||||
|
||||
- **Added XGMI table**
|
||||
- **Added XGMI table**.
|
||||
Displays XGMI information for AMD GPU devices in a table format. Only available on supported ASICs (eg. MI300). Here users can view read/write data XGMI or PCIe accumulated data transfer size (in KiloBytes).
|
||||
|
||||
```shell
|
||||
@@ -735,7 +755,7 @@ GPU7 0000:df:00.0 32 Gb/s 512 Gb/s XGMI
|
||||
|
||||
```
|
||||
|
||||
- **Added units of measure to JSON output.**
|
||||
- **Added units of measure to JSON output**.
|
||||
We added unit of measure to JSON/CSV `amd-smi metric`, `amd-smi static`, and `amd-smi monitor` commands.
|
||||
|
||||
Ex.
|
||||
@@ -769,9 +789,9 @@ amd-smi metric -p --json
|
||||
]
|
||||
```
|
||||
|
||||
### Changed
|
||||
### Changes
|
||||
|
||||
- **Topology is now left-aligned with BDF of each device listed individual table's row/coloumns.**
|
||||
- **Topology is now left-aligned with BDF of each device listed individual table's row/coloumns**.
|
||||
We provided each device's BDF for every table's row/columns, then left aligned data. We want AMD SMI Tool output to be easy to understand and digest for our users. Having users scroll up to find this information made it difficult to follow, especially for devices which have many devices associated with one ASIC.
|
||||
|
||||
```shell
|
||||
@@ -832,15 +852,11 @@ NUMA BW TABLE:
|
||||
0000:df:00.0 50000-50000 50000-50000 50000-50000 50000-50000 50000-50000 50000-50000 50000-50000 N/A
|
||||
```
|
||||
|
||||
### Optimizations
|
||||
### Fixes
|
||||
|
||||
- N/A
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Fix for Navi3X/Navi2X/MI100 `amdsmi_get_gpu_pci_bandwidth()` in frequencies_read tests**
|
||||
- **Fix for Navi3X/Navi2X/MI100 `amdsmi_get_gpu_pci_bandwidth()` in frequencies_read tests**.
|
||||
Devices which do not report (eg. Navi3X/Navi2X/MI100) we have added checks to confirm these devices return AMDSMI_STATUS_NOT_SUPPORTED. Otherwise, tests now display a return string.
|
||||
- **Fix for devices which have an older pyyaml installed**
|
||||
- **Fix for devices which have an older pyyaml installed**.
|
||||
Platforms which are identified as having an older pyyaml version or pip, we no manually update both pip and pyyaml as needed. This corrects issues identified below. Fix impacts the following CLI commands:
|
||||
- `amd-smi list`
|
||||
- `amd-smi static`
|
||||
@@ -852,43 +868,35 @@ Platforms which are identified as having an older pyyaml version or pip, we no m
|
||||
TypeError: dump_all() got an unexpected keyword argument 'sort_keys'
|
||||
```
|
||||
|
||||
- **Fix for crash when user is not a member of video/render groups**
|
||||
- **Fix for crash when user is not a member of video/render groups**.
|
||||
AMD SMI now uses same mutex handler for devices as rocm-smi. This helps avoid crashes when DRM/device data is inaccessable to the logged in user.
|
||||
|
||||
### Known Issues
|
||||
|
||||
- N/A
|
||||
|
||||
## amd_smi_lib for ROCm 6.0.0
|
||||
|
||||
### Added
|
||||
### Additions
|
||||
|
||||
- **Integrated the E-SMI (EPYC-SMI) library**
|
||||
- **Integrated the E-SMI (EPYC-SMI) library**.
|
||||
You can now query CPU-related information directly through AMD SMI. Metrics include power, energy, performance, and other system details.
|
||||
|
||||
- **Added support for gfx942 metrics**
|
||||
- **Added support for gfx942 metrics**.
|
||||
You can now query MI300 device metrics to get real-time information. Metrics include power, temperature, energy, and performance.
|
||||
|
||||
- **Compute and memory partition support**
|
||||
- **Compute and memory partition support**.
|
||||
Users can now view, set, and reset partitions. The topology display can provide a more in-depth look at the device's current configuration.
|
||||
|
||||
### Changed
|
||||
|
||||
- **GPU index sorting made consistent with other tools**
|
||||
To ensure alignment with other ROCm software tools, GPU index sorting is optimized to use Bus:Device.Function (BDF) rather than the card number.
|
||||
- **Topology output is now aligned with GPU BDF table**
|
||||
Earlier versions of the topology output were difficult to read since each GPU was displayed linearly.
|
||||
Now the information is displayed as a table by each GPU's BDF, which closer resembles rocm-smi output.
|
||||
|
||||
### Optimizations
|
||||
|
||||
- Updated to C++17, gtest-1.14, and cmake 3.14
|
||||
|
||||
### Fixed
|
||||
### Changes
|
||||
|
||||
- **Fix for driver not initialized**
|
||||
- **GPU index sorting made consistent with other tools**.
|
||||
To ensure alignment with other ROCm software tools, GPU index sorting is optimized to use Bus:Device.Function (BDF) rather than the card number.
|
||||
- **Topology output is now aligned with GPU BDF table**.
|
||||
Earlier versions of the topology output were difficult to read since each GPU was displayed linearly.
|
||||
Now the information is displayed as a table by each GPU's BDF, which closer resembles rocm-smi output.
|
||||
|
||||
### Fixes
|
||||
|
||||
- **Fix for driver not initialized**.
|
||||
If driver module is not loaded, user retrieve error reponse indicating amdgpu module is not loaded.
|
||||
|
||||
### Known Issues
|
||||
|
||||
- N/A
|
||||
|
||||
@@ -28,7 +28,7 @@ find_program(GIT NAMES git)
|
||||
|
||||
## Setup the package version based on git tags.
|
||||
set(PKG_VERSION_GIT_TAG_PREFIX "amdsmi_pkg_ver")
|
||||
get_package_version_number("24.5.2" ${PKG_VERSION_GIT_TAG_PREFIX} GIT)
|
||||
get_package_version_number("24.5.3" ${PKG_VERSION_GIT_TAG_PREFIX} GIT)
|
||||
message("Package version: ${PKG_VERSION_STR}")
|
||||
set(${AMD_SMI_LIBS_TARGET}_VERSION_MAJOR "${CPACK_PACKAGE_VERSION_MAJOR}")
|
||||
set(${AMD_SMI_LIBS_TARGET}_VERSION_MINOR "${CPACK_PACKAGE_VERSION_MINOR}")
|
||||
|
||||
@@ -79,7 +79,7 @@ amd-smi will report the version and current platform detected when running the c
|
||||
~$ amd-smi
|
||||
usage: amd-smi [-h] ...
|
||||
|
||||
AMD System Management Interface | Version: 24.5.2.0 | ROCm version: 6.1.2 | Platform: Linux Baremetal
|
||||
AMD System Management Interface | Version: 24.5.3.0 | ROCm version: 6.1.2 | Platform: Linux Baremetal
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
|
||||
@@ -1792,17 +1792,39 @@ class AMDSMICommands():
|
||||
if args.voltage_curve:
|
||||
try:
|
||||
od_volt = amdsmi_interface.amdsmi_get_gpu_od_volt_info(args.gpu)
|
||||
logging.debug(f"OD Voltage info: {od_volt}")
|
||||
|
||||
# Populate N/A values per voltage point
|
||||
voltage_point_dict = {}
|
||||
for point in range(amdsmi_interface.AMDSMI_NUM_VOLTAGE_CURVE_POINTS):
|
||||
voltage_point_dict[f'point_{point}_frequency'] = "N/A"
|
||||
voltage_point_dict[f'point_{point}_voltage'] = "N/A"
|
||||
|
||||
for point in range(3):
|
||||
# Populate voltage point values
|
||||
for point in range(amdsmi_interface.AMDSMI_NUM_VOLTAGE_CURVE_POINTS):
|
||||
if isinstance(od_volt, dict):
|
||||
logging.debug(f"point_{point} frequency: {od_volt['curve.vc_points'][point].frequency}")
|
||||
logging.debug(f"point_{point} voltage: {od_volt['curve.vc_points'][point].voltage}")
|
||||
frequency = int(od_volt["curve.vc_points"][point].frequency / 1000000)
|
||||
voltage = int(od_volt["curve.vc_points"][point].voltage)
|
||||
else:
|
||||
frequency = 0
|
||||
voltage = 0
|
||||
voltage_point_dict[f'voltage_point_{point}'] = f"{frequency} Mhz {voltage} mV"
|
||||
frequency = "N/A"
|
||||
voltage = "N/A"
|
||||
|
||||
if frequency == 0:
|
||||
frequency = "N/A"
|
||||
|
||||
if voltage == 0:
|
||||
voltage = "N/A"
|
||||
|
||||
if frequency != "N/A":
|
||||
frequency = self.helpers.unit_format(self.logger, frequency, "Mhz")
|
||||
|
||||
if voltage != "N/A":
|
||||
voltage = self.helpers.unit_format(self.logger, voltage, "mV")
|
||||
|
||||
voltage_point_dict[f'point_{point}_frequency'] = frequency
|
||||
voltage_point_dict[f'point_{point}_voltage'] = voltage
|
||||
|
||||
values_dict['voltage_curve'] = voltage_point_dict
|
||||
except amdsmi_exception.AmdSmiLibraryException as e:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
test
|
||||
@@ -48,7 +48,7 @@ PROJECT_NAME = AMD SMI
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "24.5.2.0"
|
||||
PROJECT_NUMBER = "24.5.3.0"
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@@ -907,8 +907,11 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = ../../README.md \
|
||||
INPUT = ../reference/index.rst \
|
||||
../../include/amd_smi/amdsmi.h
|
||||
|
||||
|
||||
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,255 @@
|
||||
.. meta::
|
||||
:description: Using AMD SMI
|
||||
:keywords: AMD, SMI, system, management, interface, ROCm
|
||||
|
||||
********************************
|
||||
Usage Basics for the C Library
|
||||
********************************
|
||||
|
||||
Device/Socket handles
|
||||
----------------------
|
||||
|
||||
Many of the AMD SMI library's functions take a "socket handle" or "device handle." The socket is an abstraction of the hardware's physical socket. This will enable AMD SMI to provide a better representation of the hardware to the user. Although there is always one distinct GPU for a socket, the APU may have both GPU and CPU devices on the same socket. Moreover, for the MI200 series, it may have multiple GCDs.
|
||||
|
||||
To discover the sockets in the system, `amdsmi_get_socket_handles()` is called to get a list of socket handles, which, in turn, can be used to query the devices in that socket using `amdsmi_get_processor_handles().` The device handler is used to distinguish the detected devices from one another. It is important to note that a device may end up with a different device handle after restarting the application, so a device handle should not be relied upon to be constant over the process.
|
||||
|
||||
The list of socket handles discovered using `amdsmi_get_socket_handles()`, can also be used to query the CPUs in that socket using amdsmi_get_processor_handles_by_type(), which in turn can then be used to query the cores in that CPU using amdsmi_get_processor_handles_by_type() again.
|
||||
|
||||
|
||||
Hello AMD SMI
|
||||
--------------
|
||||
|
||||
The only required AMD SMI call for any program that wants to use AMD SMI is the `amdsmi_init()` call. This call initializes some internal data structures that subsequent AMD-SMI calls will use. A flag can be passed in the call if the application is only interested in a specific device type.
|
||||
|
||||
When AMD SMI is no longer used, `amdsmi_shut_down()` should be called. This provides a way to release resources that AMD-SMI may have held.
|
||||
|
||||
1) A simple "Hello World" type program that displays the temperature of detected devices would look like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "amd_smi/amdsmi.h"
|
||||
|
||||
int main() {
|
||||
amdsmi_status_t ret;
|
||||
|
||||
// Init amdsmi for sockets and devices. Here we are only interested in AMD_GPUS.
|
||||
ret = amdsmi_init(AMDSMI_INIT_AMD_GPUS);
|
||||
|
||||
// Get all sockets
|
||||
uint32_t socket_count = 0;
|
||||
|
||||
// Get the socket count available in the system.
|
||||
ret = amdsmi_get_socket_handles(&socket_count, nullptr);
|
||||
|
||||
// Allocate the memory for the sockets
|
||||
std::vector<amdsmi_socket_handle> sockets(socket_count);
|
||||
// Get the socket handles in the system
|
||||
ret = amdsmi_get_socket_handles(&socket_count, &sockets[0]);
|
||||
|
||||
std::cout << "Total Socket: " << socket_count << std::endl;
|
||||
|
||||
// For each socket, get identifier and devices
|
||||
for (uint32_t i=0; i < socket_count; i++) {
|
||||
// Get Socket info
|
||||
char socket_info[128];
|
||||
ret = amdsmi_get_socket_info(sockets[i], 128, socket_info);
|
||||
std::cout << "Socket " << socket_info<< std::endl;
|
||||
|
||||
// Get the device count for the socket.
|
||||
uint32_t device_count = 0;
|
||||
ret = amdsmi_get_processor_handles(sockets[i], &device_count, nullptr);
|
||||
|
||||
// Allocate the memory for the device handlers on the socket
|
||||
std::vector<amdsmi_processor_handle> processor_handles(device_count);
|
||||
// Get all devices of the socket
|
||||
ret = amdsmi_get_processor_handles(sockets[i],
|
||||
&device_count, &processor_handles[0]);
|
||||
|
||||
// For each device of the socket, get name and temperature.
|
||||
for (uint32_t j=0; j < device_count; j++) {
|
||||
// Get device type. Since the amdsmi is initialized with
|
||||
// AMD_SMI_INIT_AMD_GPUS, the processor_type must be AMD_GPU.
|
||||
processor_type_t processor_type;
|
||||
ret = amdsmi_get_processor_type(processor_handles[j], &processor_type);
|
||||
if (processor_type != AMD_GPU) {
|
||||
std::cout << "Expect AMD_GPU device type!\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get device name
|
||||
amdsmi_board_info_t board_info;
|
||||
ret = amdsmi_get_gpu_board_info(processor_handles[j], &board_info);
|
||||
std::cout << "\tdevice "
|
||||
<< j <<"\n\t\tName:" << board_info.product_name << std::endl;
|
||||
|
||||
// Get temperature
|
||||
int64_t val_i64 = 0;
|
||||
ret = amdsmi_get_temp_metric(processor_handles[j], TEMPERATURE_TYPE_EDGE,
|
||||
AMDSMI_TEMP_CURRENT, &val_i64);
|
||||
std::cout << "\t\tTemperature: " << val_i64 << "C" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up resources allocated at amdsmi_init. It will invalidate sockets
|
||||
// and devices pointers
|
||||
ret = amdsmi_shut_down();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
2) A sample program that displays the power of detected cpus would look like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "amd_smi/amdsmi.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
amdsmi_status_t ret;
|
||||
uint32_t socket_count = 0;
|
||||
|
||||
// Initialize amdsmi for AMD CPUs
|
||||
ret = amdsmi_init(AMDSMI_INIT_AMD_CPUS);
|
||||
|
||||
ret = amdsmi_get_socket_handles(&socket_count, nullptr);
|
||||
|
||||
// Allocate the memory for the sockets
|
||||
std::vector<amdsmi_socket_handle> sockets(socket_count);
|
||||
|
||||
// Get the sockets of the system
|
||||
ret = amdsmi_get_socket_handles(&socket_count, &sockets[0]);
|
||||
|
||||
std::cout << "Total Socket: " << socket_count << std::endl;
|
||||
|
||||
// For each socket, get cpus
|
||||
for (uint32_t i = 0; i < socket_count; i++) {
|
||||
uint32_t cpu_count = 0;
|
||||
|
||||
// Set processor type as AMD_CPU
|
||||
processor_type_t processor_type = AMD_CPU;
|
||||
ret = amdsmi_get_processor_handles_by_type(sockets[i], processor_type, nullptr, &cpu_count);
|
||||
|
||||
// Allocate the memory for the cpus
|
||||
std::vector<amdsmi_processor_handle> plist(cpu_count);
|
||||
|
||||
// Get the cpus for each socket
|
||||
ret = amdsmi_get_processor_handles_by_type(sockets[i], processor_type, &plist[0], &cpu_count);
|
||||
|
||||
for (uint32_t index = 0; index < plist.size(); index++) {
|
||||
uint32_t socket_power;
|
||||
std::cout<<"CPU "<<index<<"\t"<< std::endl;
|
||||
std::cout<<"Power (Watts): ";
|
||||
|
||||
ret = amdsmi_get_cpu_socket_power(plist[index], &socket_power);
|
||||
if(ret != AMDSMI_STATUS_SUCCESS)
|
||||
std::cout<<"Failed to get cpu socket power"<<"["<<index<<"] , Err["<<ret<<"] "<< std::endl;
|
||||
|
||||
if (!ret) {
|
||||
std::cout<<static_cast<double>(socket_power)/1000<<std::endl;
|
||||
}
|
||||
std::cout<<std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up resources allocated at amdsmi_init
|
||||
ret = amdsmi_shut_down();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Building AMD SMI
|
||||
-----------------
|
||||
|
||||
Rebuilding Python wrapper
|
||||
==========================
|
||||
|
||||
Python wrapper (binding) is an auto-generated file `py-interface/amdsmi_wrapper.py`
|
||||
|
||||
The wrapper should be re-generated on each C++ API change by doing the following:
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./update_wrapper.sh
|
||||
|
||||
|
||||
After this command, the file in `py-interface/amdsmi_wrapper.py` will be automatically updated on each compile.
|
||||
|
||||
Note: To re-generate the Python wrapper, you must have **Docker** installed.
|
||||
|
||||
Note: Python_wrapper is NOT automatically re-generated. You must run `./update_wrapper.sh`.
|
||||
|
||||
|
||||
Additional software required for building AMD SMI
|
||||
--------------------------------------------------
|
||||
|
||||
The following components are required to build the library.
|
||||
|
||||
.. Note:: The software versions listed are what was used in development. Earlier versions are not guaranteed to work.
|
||||
|
||||
* CMake (v3.14.0) - `python3 -m pip install cmake`
|
||||
* g++ (5.4.0)
|
||||
|
||||
The following components are required to build the AMD SMI Python package:
|
||||
|
||||
* Clang (14.0 or above)
|
||||
* Python (3.6.8 or above)
|
||||
* virtualenv - `python3 -m pip install virtualenv`
|
||||
|
||||
The following tools are required to build the latest documentation:
|
||||
|
||||
* Doxygen (1.8.11)
|
||||
* Latex (pdfTeX 3.14159265-2.6-1.40.16)
|
||||
|
||||
The source code for AMD SMI is available on Github.
|
||||
|
||||
After the AMD SMI library git repository is cloned to a local Linux machine, the default location for the library and headers is /opt/rocm.
|
||||
|
||||
.. Note:: Before installation, the old ROCm directories must be deleted:
|
||||
|
||||
* /opt/rocm
|
||||
* /opt/rocm-{number}
|
||||
|
||||
Building the library is achieved by following the typical CMake build sequence (run as root user or use 'sudo' before the 'make install' command), specifically:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j $(nproc)
|
||||
make install
|
||||
|
||||
|
||||
The built library will appear in the `build` folder.
|
||||
|
||||
In addition to the preceding steps, use the following instructions to build the rpm and deb packages:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
make package
|
||||
|
||||
Building tests
|
||||
-------------------
|
||||
|
||||
To verify the build and capability of AMD SMI on your system and see an example of how AMD SMI can be used, you may build and run the tests available in the repo. To build the tests, follow these steps:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake -DBUILD_TESTS=ON ..
|
||||
make -j $(nproc)
|
||||
|
||||
|
||||
Running tests
|
||||
--------------
|
||||
|
||||
Execute the program `amdsmitst` that is built from the steps above to run the test.
|
||||
|
||||
Path to the program `amdsmitst`: `build/tests/amd_smi_test/`
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
```{include} ../README.md
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
.. meta::
|
||||
:description: AMDSMI documentation and API reference library
|
||||
:keywords: amdsmi, ROCm, API, documentation
|
||||
|
||||
********************************************************************
|
||||
AMD SMI documentation
|
||||
********************************************************************
|
||||
|
||||
The AMD System Management Interface (SMI) Library, or AMD SMI library, is a C library for Linux that provides a user space interface for applications to monitor and control AMD devices.
|
||||
|
||||
You can access the AMD SMI code on the `GitHub repository <https://github.com/ROCm/amdsmi>`_.
|
||||
|
||||
.. Note::
|
||||
|
||||
This project is a successor to `rocm_smi_lib. <https://github.com/RadeonOpenCompute/rocm_smi_lib>`_
|
||||
|
||||
.. grid:: 2
|
||||
:gutter: 3
|
||||
|
||||
.. grid-item-card:: Install
|
||||
|
||||
* :doc:`AMD SMI installation <./install/install>`
|
||||
|
||||
.. grid-item-card:: API reference
|
||||
|
||||
* :doc:`Files <../doxygen/docBin/html/files>`
|
||||
* :doc:`Globals <../doxygen/docBin/html/globals>`
|
||||
* :doc:`Data structures <../doxygen/docBin/html/annotated>`
|
||||
* :doc:`Modules <../doxygen/docBin/html/modules>`
|
||||
* :doc:`Data fields <../doxygen/docBin/html/functions_data_fields>`
|
||||
|
||||
.. grid-item-card:: How to
|
||||
|
||||
* :doc:`Use AMD SMI for C++ library <how-to/using-amdsmi-for-C++>`
|
||||
* :doc:`Use AMD SMI for Python library <how-to/using-amdsmi-for-python>`
|
||||
* :doc:`Use AMD SMI CLI tool <how-to/using-AMD-SMI-CLI-tool>`
|
||||
|
||||
|
||||
.. grid-item-card:: Tutorials
|
||||
|
||||
* `AMD SMI GitHub samples <https://github.com/ROCm/amdsmi/tree/develop/example>`_
|
||||
* `ROCm SMI Github samples <https://github.com/ROCm/rocm_smi_lib/tree/develop/docs>`_
|
||||
|
||||
|
||||
To contribute to the documentation, refer to
|
||||
`Contributing to ROCm <https://rocm.docs.amd.com/en/latest/contribute/contributing.html>`_.
|
||||
|
||||
You can find licensing information on the
|
||||
`Licensing <https://rocm.docs.amd.com/en/latest/about/license.html>`_ page.
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
.. meta::
|
||||
:description: Install AMD SMI
|
||||
:keywords: install, SMI, AMD, ROCm
|
||||
|
||||
********************************************************************
|
||||
Installation
|
||||
********************************************************************
|
||||
|
||||
AMD System Management Interface (AMD SMI) library
|
||||
-------------------------------------------------
|
||||
|
||||
The AMD System Management Interface Library (AMD SMI library) is a C library for Linux that provides a user space interface for applications to monitor and control AMD devices.
|
||||
|
||||
.. Note::
|
||||
|
||||
This project is a successor to `rocm_smi_lib. <https://github.com/RadeonOpenCompute/rocm_smi_lib>`_
|
||||
|
||||
Supported platforms
|
||||
=====================
|
||||
In its initial release, the AMD SMI library supports Linux bare metal and Linux virtual machine guest for AMD GPUs. In a future release, the library will extend to support AMD EPYC™ CPUs.
|
||||
|
||||
The AMD SMI library can run on AMD ROCm-supported platforms. Refer to `System requirements - Linux <https://rocm.docs.amd.com/projects/install-on-linux/en/latest/reference/system-requirements.html>`_ for more information.
|
||||
|
||||
To run the AMD SMI library, the `amdgpu` driver and the `hsmp` driver must be installed. Optionally, `libdrm` can be installed to query firmware information and hardware IPs.
|
||||
|
||||
|
||||
CLI tool and libraries installation
|
||||
------------------------------------
|
||||
|
||||
Requirements
|
||||
=============
|
||||
|
||||
* Python 3.6.8+ 64-bit
|
||||
* amdgpu driver must be loaded for `amdsmi_init()` to pass
|
||||
|
||||
Installation steps
|
||||
-------------------
|
||||
|
||||
1. Install amdgpu using ROCm.
|
||||
|
||||
2. Install amdgpu driver. See the following example. Note that your release and link may differ. The `amdgpu-install --usecase=rocm` triggers both the amdgpu driver update and AMD SMI packages to be installed on your device.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo apt update
|
||||
|
||||
wget https://repo.radeon.com/amdgpu-install/6.0.2/ubuntu/jammy/amdgpu-install_6.0.60002-1_all.deb
|
||||
|
||||
sudo apt install ./amdgpu-install_6.0.60002-1_all.deb
|
||||
|
||||
sudo amdgpu-install --usecase=rocm
|
||||
|
||||
amd-smi --help
|
||||
|
||||
3. Install an example for Ubuntu 22.04 (without ROCm).
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
apt install amd-smi-lib
|
||||
|
||||
# if installed with rocm ignore the export
|
||||
|
||||
export PATH="${PATH:+${PATH}:}~/opt/rocm/bin"
|
||||
|
||||
amd-smi --help
|
||||
|
||||
|
||||
Optional autocompletion
|
||||
------------------------
|
||||
|
||||
The `amd-smi` cli application supports autocompletion. The package should attempt to install it, if argcomplete is not installed, you can enable it by using the following commands:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
python3 -m pip install argcomplete
|
||||
|
||||
activate-global-python-argcomplete --user
|
||||
|
||||
# restart shell to enable
|
||||
|
||||
|
||||
Manual/Multiple ROCm instance Python library install
|
||||
------------------------------------------------------
|
||||
|
||||
In the event there are multiple ROCm installations and `pyenv` is not being used to use the correct amdsmi version, you must uninstall previous versions of AMD SMI and install the latest version you want directly from your ROCm instance.
|
||||
|
||||
Python library install example for Ubuntu 22.04
|
||||
=================================================
|
||||
|
||||
1. Remove any existing AMD SMI installation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python3 -m pip list | grep amd
|
||||
|
||||
python3 -m pip uninstall amdsmi
|
||||
|
||||
|
||||
2. Install Python library from your target ROCm instance:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
apt install amd-smi-lib
|
||||
|
||||
cd /opt/rocm/share/amd_smi
|
||||
|
||||
python3 -m pip install --upgrade pip
|
||||
|
||||
python3 -m pip install --user
|
||||
|
||||
|
||||
Now you have the AMD SMI Python library in your Python path:
|
||||
|
||||
|
||||
.. code:: bash
|
||||
|
||||
~$ python3
|
||||
|
||||
Python 3.8.10 (default, May 26 2023, 14:05:08)
|
||||
|
||||
[GCC 9.4.0] on linux
|
||||
|
||||
3. Type "help", "copyright", "credits" or "license" for more information
|
||||
|
||||
.. code:: bash
|
||||
|
||||
import amdsmi
|
||||
|
||||
|
||||
Sphinx documentation
|
||||
=====================
|
||||
|
||||
Run the following commands to build the documentation locally:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd docs
|
||||
|
||||
python3 -m pip install -r sphinx/requirements.txt
|
||||
|
||||
python3 -m sphinx -T -E -b html -d _build/doctrees -D language=en . _build/html
|
||||
|
||||
|
||||
The output is available in `docs/_build/html`.
|
||||
|
||||
For additional details, see `Contribute to ROCm documentation <https://rocm.docs.amd.com/en/latest/contribute/contributing.html>`_.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
.. meta::
|
||||
:description: Install AMD SMI
|
||||
:keywords: install, SMI, AMD, ROCm
|
||||
|
||||
******************
|
||||
API reference
|
||||
******************
|
||||
|
||||
This section provides technical descriptions and important information about the different AMD SMI and library components.
|
||||
|
||||
* {doc}`Library <../doxygen/docBin/html/files>`
|
||||
* {doc}`Functions <../doxygen/docBin/html/globals>`
|
||||
* {doc}`Data structures <../doxygen/docBin/html/annotated>`
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
====================
|
||||
C++ Tutorials
|
||||
====================
|
||||
|
||||
This chapter contains the ROCm SMI C++ API tutorials.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rocm_smi/rocm_smi.h"
|
||||
int main() {
|
||||
|
||||
rsmi_status_t ret;
|
||||
uint32_t num_devices;
|
||||
uint16_t dev_id;
|
||||
|
||||
// We will skip return code checks for this example, but it
|
||||
// is recommended to always check this as some calls may not
|
||||
// apply for some devices or ROCm releases
|
||||
|
||||
ret = rsmi_init(0);
|
||||
ret = rsmi_num_monitor_devices(&num_devices);
|
||||
|
||||
for (int i=0; i < num_devices; ++i) {
|
||||
ret = rsmi_dev_id_get(i, &dev_id);
|
||||
// dev_id holds the device ID of device i, upon a
|
||||
// successful call
|
||||
}
|
||||
ret = rsmi_shut_down();
|
||||
return 0;
|
||||
}
|
||||
|
||||
For more examples please check the `C++ example <https://github.com/ROCm/rocm_smi_lib/blob/develop/rocm_smi/example/rocm_smi_example.cc>`_
|
||||
or `tests. <https://github.com/ROCm/rocm_smi_lib/tree/develop/tests/rocm_smi_test/functional>`_
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
.. meta::
|
||||
:description: ROCm SMI documentation and API reference library
|
||||
:keywords: SMI, ROCm, API, documentation
|
||||
|
||||
|
||||
****************************************************
|
||||
ROCm System Management Interface (ROCm SMI) library
|
||||
****************************************************
|
||||
|
||||
The ROCm System Management Interface Library, or ROCm SMI library, is part of the ROCm software stack. It is a C library for Linux that provides a user space interface for applications to monitor and control GPU applications.
|
||||
|
||||
ROCm SMI Library still works in the current release, but its documentation is now integrated with AMD SMI. For information specific to ROCm SMI Library, refer to `ROCm SMI Library <https://github.com/ROCm/rocm_smi_lib/>`_
|
||||
@@ -0,0 +1,269 @@
|
||||
====================
|
||||
Python API Reference
|
||||
====================
|
||||
|
||||
This chapter describes the ROCm SMI Python module API.
|
||||
|
||||
.. default-domain:: py
|
||||
.. py:currentmodule:: rocm_smi
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. autofunction:: rocm_smi.driverInitialized
|
||||
|
||||
.. autofunction:: rocm_smi.formatJson
|
||||
|
||||
.. autofunction:: rocm_smi.formatCsv
|
||||
|
||||
.. autofunction:: rocm_smi.formatMatrixToJSON
|
||||
|
||||
.. autofunction:: rocm_smi.getBus
|
||||
|
||||
.. autofunction:: rocm_smi.getFanSpeed
|
||||
|
||||
.. autofunction:: rocm_smi.getGpuUse
|
||||
|
||||
.. autofunction:: rocm_smi.getDRMDeviceId
|
||||
|
||||
.. autofunction:: rocm_smi.getSubsystemId
|
||||
|
||||
.. autofunction:: rocm_smi.getVendor
|
||||
|
||||
.. autofunction:: rocm_smi.getGUID
|
||||
|
||||
.. autofunction:: rocm_smi.getTargetGfxVersion
|
||||
|
||||
.. autofunction:: rocm_smi.getNodeId
|
||||
|
||||
.. autofunction:: rocm_smi.getDeviceName
|
||||
|
||||
.. autofunction:: rocm_smi.getRev
|
||||
|
||||
.. autofunction:: rocm_smi.getMaxPower
|
||||
|
||||
.. autofunction:: rocm_smi.getMemInfo
|
||||
|
||||
.. autofunction:: rocm_smi.getProcessName
|
||||
|
||||
.. autofunction:: rocm_smi.getPerfLevel
|
||||
|
||||
.. autofunction:: rocm_smi.getPid
|
||||
|
||||
.. autofunction:: rocm_smi.getPidList
|
||||
|
||||
.. autofunction:: rocm_smi.getPower
|
||||
|
||||
.. autofunction:: rocm_smi.getRasEnablement
|
||||
|
||||
.. autofunction:: rocm_smi.getTemp
|
||||
|
||||
.. autofunction:: rocm_smi.findFirstAvailableTemp
|
||||
|
||||
.. autofunction:: rocm_smi.getTemperatureLabel
|
||||
|
||||
.. autofunction:: rocm_smi.getPowerLabel
|
||||
|
||||
.. autofunction:: rocm_smi.getVbiosVersion
|
||||
|
||||
.. autofunction:: rocm_smi.getVersion
|
||||
|
||||
.. autofunction:: rocm_smi.getComputePartition
|
||||
|
||||
.. autofunction:: rocm_smi.getMemoryPartition
|
||||
|
||||
.. autofunction:: rocm_smi.print2DArray
|
||||
|
||||
.. autofunction:: rocm_smi.printEmptyLine
|
||||
|
||||
.. autofunction:: rocm_smi.printErrLog
|
||||
|
||||
.. autofunction:: rocm_smi.printInfoLog
|
||||
|
||||
.. autofunction:: rocm_smi.printEventList
|
||||
|
||||
.. autofunction:: rocm_smi.printLog
|
||||
|
||||
.. autofunction:: rocm_smi.printListLog
|
||||
|
||||
.. autofunction:: rocm_smi.printLogSpacer
|
||||
|
||||
.. autofunction:: rocm_smi.printSysLog
|
||||
|
||||
.. autofunction:: rocm_smi.printTableLog
|
||||
|
||||
.. autofunction:: rocm_smi.printTableRow
|
||||
|
||||
.. autofunction:: rocm_smi.checkIfSecondaryDie
|
||||
|
||||
.. autofunction:: rocm_smi.resetClocks
|
||||
|
||||
.. autofunction:: rocm_smi.resetFans
|
||||
|
||||
.. autofunction:: rocm_smi.resetPowerOverDrive
|
||||
|
||||
.. autofunction:: rocm_smi.resetProfile
|
||||
|
||||
.. autofunction:: rocm_smi.resetXgmiErr
|
||||
|
||||
.. autofunction:: rocm_smi.resetPerfDeterminism
|
||||
|
||||
.. autofunction:: rocm_smi.resetComputePartition
|
||||
|
||||
.. autofunction:: rocm_smi.resetMemoryPartition
|
||||
|
||||
.. autofunction:: rocm_smi.setClockRange
|
||||
|
||||
.. autofunction:: rocm_smi.setClockExtremum
|
||||
|
||||
.. autofunction:: rocm_smi.setVoltageCurve
|
||||
|
||||
.. autofunction:: rocm_smi.setPowerPlayTableLevel
|
||||
|
||||
.. autofunction:: rocm_smi.setClockOverDrive
|
||||
|
||||
.. autofunction:: rocm_smi.setClocks
|
||||
|
||||
.. autofunction:: rocm_smi.setPerfDeterminism
|
||||
|
||||
.. autofunction:: rocm_smi.resetGpu
|
||||
|
||||
.. autofunction:: rocm_smi.isRasControlAvailable
|
||||
|
||||
.. autofunction:: rocm_smi.setRas
|
||||
|
||||
.. autofunction:: rocm_smi.setFanSpeed
|
||||
|
||||
.. autofunction:: rocm_smi.setPerformanceLevel
|
||||
|
||||
.. autofunction:: rocm_smi.setPowerOverDrive
|
||||
|
||||
.. autofunction:: rocm_smi.setProfile
|
||||
|
||||
.. autofunction:: rocm_smi.setComputePartition
|
||||
|
||||
.. autofunction:: rocm_smi.progressbar
|
||||
|
||||
.. autofunction:: rocm_smi.showProgressbar
|
||||
|
||||
.. autofunction:: rocm_smi.setMemoryPartition
|
||||
|
||||
.. autofunction:: rocm_smi.showVersion
|
||||
|
||||
.. autofunction:: rocm_smi.showAllConcise
|
||||
|
||||
.. autofunction:: rocm_smi.showAllConciseHw
|
||||
|
||||
.. autofunction:: rocm_smi.showBus
|
||||
|
||||
.. autofunction:: rocm_smi.showClocks
|
||||
|
||||
.. autofunction:: rocm_smi.showCurrentClocks
|
||||
|
||||
.. autofunction:: rocm_smi.showCurrentFans
|
||||
|
||||
.. autofunction:: rocm_smi.showCurrentTemps
|
||||
|
||||
.. autofunction:: rocm_smi.showFwInfo
|
||||
|
||||
.. autofunction:: rocm_smi.showGpusByPid
|
||||
|
||||
.. autofunction:: rocm_smi.getCoarseGrainUtil
|
||||
|
||||
.. autofunction:: rocm_smi.showGpuUse
|
||||
|
||||
.. autofunction:: rocm_smi.showEnergy
|
||||
|
||||
.. autofunction:: rocm_smi.showId
|
||||
|
||||
.. autofunction:: rocm_smi.showMaxPower
|
||||
|
||||
.. autofunction:: rocm_smi.showMemInfo
|
||||
|
||||
.. autofunction:: rocm_smi.showMemUse
|
||||
|
||||
.. autofunction:: rocm_smi.showMemVendor
|
||||
|
||||
.. autofunction:: rocm_smi.showOverDrive
|
||||
|
||||
.. autofunction:: rocm_smi.showPcieBw
|
||||
|
||||
.. autofunction:: rocm_smi.showPcieReplayCount
|
||||
|
||||
.. autofunction:: rocm_smi.showPerformanceLevel
|
||||
|
||||
.. autofunction:: rocm_smi.showPids
|
||||
|
||||
.. autofunction:: rocm_smi.showPower
|
||||
|
||||
.. autofunction:: rocm_smi.showPowerPlayTable
|
||||
|
||||
.. autofunction:: rocm_smi.showProduct
|
||||
|
||||
.. autofunction:: rocm_smi.showProfile
|
||||
|
||||
.. autofunction:: rocm_smi.showRange
|
||||
|
||||
.. autofunction:: rocm_smi.showRasInfo
|
||||
|
||||
.. autofunction:: rocm_smi.showRetiredPages
|
||||
|
||||
.. autofunction:: rocm_smi.showSerialNumber
|
||||
|
||||
.. autofunction:: rocm_smi.showUId
|
||||
|
||||
.. autofunction:: rocm_smi.showVbiosVersion
|
||||
|
||||
.. autofunction:: rocm_smi.showEvents
|
||||
|
||||
.. autofunction:: rocm_smi.showDriverVersion
|
||||
|
||||
.. autofunction:: rocm_smi.showVoltage
|
||||
|
||||
.. autofunction:: rocm_smi.showVoltageCurve
|
||||
|
||||
.. autofunction:: rocm_smi.showXgmiErr
|
||||
|
||||
.. autofunction:: rocm_smi.showAccessibleTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showWeightTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showHopsTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showTypeTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showNumaTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showHwTopology
|
||||
|
||||
.. autofunction:: rocm_smi.showNodesBw
|
||||
|
||||
.. autofunction:: rocm_smi.showComputePartition
|
||||
|
||||
.. autofunction:: rocm_smi.showMemoryPartition
|
||||
|
||||
.. autofunction:: rocm_smi.checkAmdGpus
|
||||
|
||||
.. autofunction:: rocm_smi.component_str
|
||||
|
||||
.. autofunction:: rocm_smi.confirmOutOfSpecWarning
|
||||
|
||||
.. autofunction:: rocm_smi.doesDeviceExist
|
||||
|
||||
.. autofunction:: rocm_smi.initializeRsmi
|
||||
|
||||
.. autofunction:: rocm_smi.isAmdDevice
|
||||
|
||||
.. autofunction:: rocm_smi.listDevices
|
||||
|
||||
.. autofunction:: rocm_smi.load
|
||||
|
||||
.. autofunction:: rocm_smi.padHexValue
|
||||
|
||||
.. autofunction:: rocm_smi.profileString
|
||||
|
||||
.. autofunction:: rocm_smi.relaunchAsSudo
|
||||
|
||||
.. autofunction:: rocm_smi.rsmi_ret_ok
|
||||
|
||||
.. autofunction:: rocm_smi.save
|
||||
@@ -0,0 +1,29 @@
|
||||
====================
|
||||
Python Tutorials
|
||||
====================
|
||||
|
||||
This chapter is the rocm_smi Python api tutorials.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
sys.path.append("/opt/rocm/libexec/rocm_smi/")
|
||||
try:
|
||||
import rocm_smi
|
||||
except ImportError:
|
||||
raise ImportError("Could not import /opt/rocm/libexec/rocm_smi/rocm_smi.py")
|
||||
|
||||
class prof_utils:
|
||||
def __init__(self, mode) -> None:
|
||||
rocm_smi.initializeRsmi()
|
||||
|
||||
def getPower(self, device):
|
||||
return rocm_smi.getPower(device)
|
||||
|
||||
def listDevices(self):
|
||||
return rocm_smi.listDevices()
|
||||
|
||||
def getMemInfo(self, device):
|
||||
(memUsed, memTotal) = rocm_smi.getMemInfo(device, "vram")
|
||||
return round(float(memUsed)/float(memTotal) * 100, 2)
|
||||
|
||||
@@ -1,26 +1,49 @@
|
||||
# Anywhere {branch} is used, the branch name will be substituted.
|
||||
# These comments will also be removed.
|
||||
defaults:
|
||||
numbered: False
|
||||
maxdepth: 6
|
||||
numbered: false
|
||||
root: index
|
||||
subtrees:
|
||||
- caption: AMD SMI APIs
|
||||
entries:
|
||||
- file: doxygen/docBin/html/index
|
||||
title: C
|
||||
- file: py-interface_readme_link
|
||||
title: Python
|
||||
- caption: CLI Tools
|
||||
entries:
|
||||
- file: amdsmi_cli_readme_link
|
||||
title: Python CLI Tool
|
||||
- file: amdsmi_release_notes_link
|
||||
title: Python CLI Release Notes
|
||||
- caption: Changelog
|
||||
entries:
|
||||
- file: amdsmi_changelog_link
|
||||
title: AMD-SMI Changelog
|
||||
- caption: About
|
||||
entries:
|
||||
- file: license
|
||||
subtrees:
|
||||
- entries:
|
||||
- file: what-is-AMDSMI.rst
|
||||
title: What is AMD SMI?
|
||||
|
||||
- caption: Install
|
||||
entries:
|
||||
- file: install/install.rst
|
||||
title: AMD SMI installation
|
||||
|
||||
|
||||
- caption: How to
|
||||
entries:
|
||||
- file: how-to/using-amdsmi-for-C++.rst
|
||||
title: Use AMD SMI for C++ library
|
||||
- file: how-to/using-amdsmi-for-python.md
|
||||
title: Use AMD SMI for Python library
|
||||
- file: how-to/using-AMD-SMI-CLI-tool.md
|
||||
title: Use AMD SMI CLI tool
|
||||
|
||||
- caption: API reference
|
||||
entries:
|
||||
- file: doxygen/docBin/html/files
|
||||
title: Files
|
||||
- file: doxygen/docBin/html/globals
|
||||
title: Globals
|
||||
- file: doxygen/docBin/html/annotated
|
||||
title: Data structures
|
||||
- file: doxygen/docBin/html/modules
|
||||
title: Modules
|
||||
- file: doxygen/docBin/html/functions_data_fields
|
||||
title: Data fields
|
||||
|
||||
|
||||
|
||||
- caption: Tutorials
|
||||
entries:
|
||||
- url: https://github.com/ROCm/amdsmi/tree/develop/example
|
||||
title: AMD SMI GitHub samples
|
||||
- url: https://github.com/ROCm/rocm_smi_lib/tree/develop/docs
|
||||
title: ROCm SMI lib GitHub samples
|
||||
|
||||
- caption: About
|
||||
entries:
|
||||
- file: license.md
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ typedef enum {
|
||||
#define AMDSMI_MAX_DEVICES 32
|
||||
#define AMDSMI_MAX_NAME 32
|
||||
#define AMDSMI_MAX_DRIVER_VERSION_LENGTH 80
|
||||
#define AMDSMI_PRODUCT_NAME_LENGTH 128
|
||||
#define AMDSMI_256_LENGTH 256
|
||||
#define AMDSMI_MAX_CONTAINER_TYPE 2
|
||||
#define AMDSMI_MAX_CACHE_TYPES 10
|
||||
#define AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK 64
|
||||
@@ -154,7 +154,7 @@ typedef enum {
|
||||
#define AMDSMI_LIB_VERSION_MAJOR 5
|
||||
|
||||
//! Minor version should be updated for each API change, but without changing headers
|
||||
#define AMDSMI_LIB_VERSION_MINOR 2
|
||||
#define AMDSMI_LIB_VERSION_MINOR 3
|
||||
|
||||
//! Release version should be set to 0 as default and can be updated by the PMs for each CSP point release
|
||||
#define AMDSMI_LIB_VERSION_RELEASE 0
|
||||
@@ -573,7 +573,7 @@ typedef struct {
|
||||
} amdsmi_fw_info_t;
|
||||
|
||||
typedef struct {
|
||||
char market_name[AMDSMI_MAX_STRING_LENGTH];
|
||||
char market_name[AMDSMI_256_LENGTH];
|
||||
uint32_t vendor_id; //< Use 32 bit to be compatible with other platform.
|
||||
char vendor_name[AMDSMI_MAX_STRING_LENGTH];
|
||||
uint32_t subvendor_id; //< The subsystem vendor id
|
||||
@@ -619,11 +619,11 @@ typedef struct {
|
||||
} amdsmi_driver_info_t;
|
||||
|
||||
typedef struct {
|
||||
char model_number[AMDSMI_NORMAL_STRING_LENGTH];
|
||||
char model_number[AMDSMI_256_LENGTH];
|
||||
char product_serial[AMDSMI_NORMAL_STRING_LENGTH];
|
||||
char fru_id[AMDSMI_NORMAL_STRING_LENGTH];
|
||||
char product_name[AMDSMI_PRODUCT_NAME_LENGTH];
|
||||
char manufacturer_name[AMDSMI_NORMAL_STRING_LENGTH];
|
||||
char product_name[AMDSMI_256_LENGTH];
|
||||
char manufacturer_name[AMDSMI_MAX_STRING_LENGTH];
|
||||
uint32_t reserved[32];
|
||||
} amdsmi_board_info_t;
|
||||
|
||||
@@ -1255,7 +1255,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
amdsmi_range_t curr_sclk_range; //!< The current SCLK frequency range
|
||||
amdsmi_range_t curr_mclk_range; //!< The current MCLK frequency range;
|
||||
//!< (upper bound only)
|
||||
//!< (upper bound only)
|
||||
amdsmi_range_t sclk_freq_limits; //!< The range possible of SCLK values
|
||||
amdsmi_range_t mclk_freq_limits; //!< The range possible of MCLK values
|
||||
|
||||
@@ -2967,8 +2967,9 @@ amdsmi_status_t amdsmi_get_clk_freq(amdsmi_processor_handle processor_handle,
|
||||
amdsmi_status_t amdsmi_reset_gpu(amdsmi_processor_handle processor_handle);
|
||||
|
||||
/**
|
||||
* @brief This function retrieves the voltage/frequency curve information. It is
|
||||
* not supported on virtual machine guest
|
||||
* @brief This function retrieves the overdrive GFX & MCLK information. If valid
|
||||
* for the GPU it will also populate the voltage curve data. It is not supported
|
||||
* on virtual machine guest
|
||||
*
|
||||
* @platform{gpu_bm_linux}
|
||||
*
|
||||
@@ -3054,14 +3055,14 @@ amdsmi_status_t amdsmi_get_gpu_metrics_info(amdsmi_processor_handle processor_ha
|
||||
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
|
||||
* metrics is allocated for pm_metrics array as input, and the number of metrics retreived
|
||||
* as output. If this parameter is NULL, this function will return
|
||||
* ::AMDSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
|
||||
* ::AMDSMI_STATUS_INVAL if the function is supported with the provided,
|
||||
* arguments and ::AMDSMI_STATUS_NOT_SUPPORTED if it is not supported with the
|
||||
* provided arguments.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function with the given arguments
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
*
|
||||
*/
|
||||
amdsmi_status_t amdsmi_get_gpu_pm_metrics_info(
|
||||
@@ -3092,14 +3093,14 @@ amdsmi_status_t amdsmi_get_gpu_pm_metrics_info(
|
||||
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
|
||||
* metrics is allocated for reg_metrics array as input, and the number of metrics retreived
|
||||
* as output. If this parameter is NULL, this function will return
|
||||
* ::AMDSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
|
||||
* ::AMDSMI_STATUS_INVAL if the function is supported with the provided,
|
||||
* arguments and ::AMDSMI_STATUS_NOT_SUPPORTED if it is not supported with the
|
||||
* provided arguments.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function with the given arguments
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
*
|
||||
*/
|
||||
amdsmi_status_t amdsmi_get_gpu_reg_table_info(
|
||||
@@ -3504,7 +3505,7 @@ amdsmi_status_t amdsmi_set_gpu_process_isolation(amdsmi_processor_handle process
|
||||
* @platform{gpu_bm_linux} @platform{guest_1vf}
|
||||
*
|
||||
* @details Given a processor handle @p processor_handle, and a sclean flag @p sclean,
|
||||
* this function will clear the SRAM data of this processor. This can be called between
|
||||
* this function will clear the SRAM data of this processor. This can be called between
|
||||
* user logins to prevent information leak.
|
||||
*
|
||||
* @note This function requires root access
|
||||
@@ -4222,7 +4223,7 @@ amdsmi_is_P2P_accessible(amdsmi_processor_handle processor_handle_src,
|
||||
* , suggested length is 4 or greater.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_UNEXPECTED_DATA data provided to function is not valid
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function
|
||||
@@ -4252,7 +4253,7 @@ amdsmi_get_gpu_compute_partition(amdsmi_processor_handle processor_handle,
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_PERMISSION function requires root access
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_SETTING_UNAVAILABLE the provided setting is
|
||||
* unavailable for current device
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
@@ -4312,7 +4313,7 @@ amdsmi_status_t amdsmi_reset_gpu_compute_partition(amdsmi_processor_handle proce
|
||||
* suggested length is 5 or greater.
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_UNEXPECTED_DATA data provided to function is not valid
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function
|
||||
@@ -4341,7 +4342,7 @@ amdsmi_get_gpu_memory_partition(amdsmi_processor_handle processor_handle,
|
||||
*
|
||||
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
|
||||
* @retval ::AMDSMI_STATUS_PERMISSION function requires root access
|
||||
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_INVAL the provided arguments are not valid
|
||||
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
|
||||
* support this function
|
||||
* @retval ::AMDSMI_STATUS_AMDGPU_RESTART_ERR could not successfully restart
|
||||
|
||||
@@ -1224,7 +1224,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_set_gpu_pci_bandwidth(device, 0)
|
||||
amdsmi_set_gpu_pci_bandwidth(device, 0)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -1620,7 +1620,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_set_gpu_od_clk_info(
|
||||
amdsmi_set_gpu_od_clk_info(
|
||||
device,
|
||||
AmdSmiFreqInd.AMDSMI_FREQ_IND_MAX,
|
||||
1000,
|
||||
@@ -1691,7 +1691,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_set_gpu_od_volt_info(device, 1, 1000, 980)
|
||||
amdsmi_set_gpu_od_volt_info(device, 1, 1000, 980)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2168,15 +2168,16 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_get_clk_freq(device, AmdSmiClkType.SYS)
|
||||
amdsmi_get_clk_freq(device, AmdSmiClkType.SYS)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
### amdsmi_get_gpu_od_volt_info
|
||||
|
||||
Description: This function retrieves the voltage/frequency curve information
|
||||
It is not supported on virtual machine guest
|
||||
Description: This function retrieves the voltage/frequency curve information.
|
||||
If the num_regions is 0 then the voltage curve is not supported.
|
||||
It is not supported on virtual machine guest.
|
||||
|
||||
Input parameters:
|
||||
|
||||
@@ -2190,8 +2191,8 @@ Field | Description
|
||||
`curr_mclk_range` | <table> <thead><tr><th> Subfield </th><th>Description</th></tr></thead><tbody><tr><td>`lower_bound`</td><td>lower bound mclk range</td></tr><tr><td>`upper_bound`</td><td>upper bound mclk range</td></tr></tbody></table>
|
||||
`sclk_freq_limits` | <table> <thead><tr><th> Subfield </th><th>Description</th></tr></thead><tbody><tr><td>`lower_bound`</td><td>lower bound sclk range limt</td></tr><tr><td>`upper_bound`</td><td>upper bound sclk range limit</td></tr></tbody></table>
|
||||
`mclk_freq_limits` | <table> <thead><tr><th> Subfield </th><th>Description</th></tr></thead><tbody><tr><td>`lower_bound`</td><td>lower bound mclk range limit</td></tr><tr><td>`upper_bound`</td><td>upper bound mclk range limit</td></tr></tbody></table>
|
||||
`curve.vc_points` | The number of supported frequencies
|
||||
`num_regions` | The current frequency index
|
||||
`curve.vc_points` | List of voltage curve points
|
||||
`num_regions` | The number of voltage curve regions
|
||||
|
||||
Exceptions that can be thrown by `amdsmi_get_gpu_od_volt_info` function:
|
||||
|
||||
@@ -2208,7 +2209,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_get_gpu_od_volt_info(dev)
|
||||
amdsmi_get_gpu_od_volt_info(dev)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2300,7 +2301,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_get_gpu_metrics_info(dev)
|
||||
amdsmi_get_gpu_metrics_info(dev)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2337,7 +2338,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_get_gpu_od_volt_curve_regions(device, 3)
|
||||
amdsmi_get_gpu_od_volt_curve_regions(device, 3)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2375,7 +2376,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_get_gpu_power_profile_presets(device, 0)
|
||||
amdsmi_get_gpu_power_profile_presets(device, 0)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2604,7 +2605,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_set_gpu_perf_level(device, AmdSmiDevPerfLevel.STABLE_PEAK)
|
||||
amdsmi_set_gpu_perf_level(device, AmdSmiDevPerfLevel.STABLE_PEAK)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
@@ -2907,7 +2908,7 @@ try:
|
||||
print("No GPUs on machine")
|
||||
else:
|
||||
for device in devices:
|
||||
amdsmi_set_gpu_overdrive_level(device, 0)
|
||||
amdsmi_set_gpu_overdrive_level(device, 0)
|
||||
except AmdSmiException as e:
|
||||
print(e)
|
||||
```
|
||||
|
||||
@@ -39,6 +39,37 @@ AMDSMI_MAX_NUM_VCN = 4
|
||||
AMDSMI_MAX_NUM_CLKS = 4
|
||||
AMDSMI_MAX_NUM_XGMI_LINKS = 8
|
||||
AMDSMI_MAX_NUM_GFX_CLKS = 8
|
||||
AMDSMI_MAX_AID = 4
|
||||
AMDSMI_MAX_ENGINES = 8
|
||||
AMDSMI_MAX_NUM_JPEG = 32
|
||||
|
||||
# Max number of DPM policies
|
||||
AMDSMI_MAX_NUM_PM_POLICIES = 32
|
||||
|
||||
# Max supported frequencies
|
||||
AMDSMI_MAX_NUM_FREQUENCIES = 33
|
||||
|
||||
# Max Fan speed
|
||||
AMDSMI_MAX_FAN_SPEED = 255
|
||||
|
||||
# Max Votlage Curve Points
|
||||
AMDSMI_NUM_VOLTAGE_CURVE_POINTS = 3
|
||||
|
||||
# Max size definitions
|
||||
AMDSMI_MAX_MM_IP_COUNT = 8
|
||||
AMDSMI_MAX_DATE_LENGTH = 32
|
||||
AMDSMI_MAX_STRING_LENGTH = 64
|
||||
AMDSMI_NORMAL_STRING_LENGTH = 32
|
||||
AMDSMI_MAX_DEVICES = 32
|
||||
AMDSMI_MAX_NAME = 32
|
||||
AMDSMI_MAX_DRIVER_VERSION_LENGTH = 80
|
||||
AMDSMI_256_LENGTH = 256
|
||||
AMDSMI_MAX_CONTAINER_TYPE = 2
|
||||
AMDSMI_MAX_CACHE_TYPES = 10
|
||||
AMDSMI_MAX_NUM_XGMI_PHYSICAL_LINK = 64
|
||||
AMDSMI_GPU_UUID_SIZE = 38
|
||||
MAX_AMDSMI_NAME_LENGTH = 64
|
||||
MAX_EVENT_NOTIFICATION_MSG_SIZE = 64
|
||||
|
||||
|
||||
class AmdSmiInitFlags(IntEnum):
|
||||
@@ -224,7 +255,6 @@ class AmdSmiEvtNotificationType(IntEnum):
|
||||
GPU_POST_RESET = amdsmi_wrapper.AMDSMI_EVT_NOTIF_GPU_POST_RESET
|
||||
RING_HANG = amdsmi_wrapper.AMDSMI_EVT_NOTIF_RING_HANG
|
||||
|
||||
|
||||
class AmdSmiTemperatureMetric(IntEnum):
|
||||
CURRENT = amdsmi_wrapper.AMDSMI_TEMP_CURRENT
|
||||
MAX = amdsmi_wrapper.AMDSMI_TEMP_MAX
|
||||
@@ -539,6 +569,21 @@ def _make_amdsmi_bdf_from_list(bdf):
|
||||
amdsmi_bdf.fields.domain_number = bdf[0]
|
||||
return amdsmi_bdf
|
||||
|
||||
def _padHexValue(value, length):
|
||||
""" Pad a hexadecimal value with a given length of zeros
|
||||
|
||||
:param value: A hexadecimal value to be padded with zeros
|
||||
:param length: Number of zeros to pad the hexadecimal value
|
||||
:param return original string string or
|
||||
padded hex of confirmed hex output (using length provided)
|
||||
"""
|
||||
# Ensure value entered meets the minimum length and is hexadecimal
|
||||
if len(value) > 2 and length > 1 and value[:2].lower() == '0x' \
|
||||
and all(c in '0123456789abcdefABCDEF' for c in value[2:]):
|
||||
# Pad with zeros after '0x' prefix
|
||||
return '0x' + value[2:].zfill(length)
|
||||
return value
|
||||
|
||||
|
||||
def amdsmi_get_socket_handles() -> List[amdsmi_wrapper.amdsmi_socket_handle]:
|
||||
"""
|
||||
@@ -1585,12 +1630,12 @@ def amdsmi_get_gpu_asic_info(
|
||||
)
|
||||
|
||||
asic_info = {
|
||||
"market_name": asic_info_struct.market_name.decode("utf-8"),
|
||||
"market_name": _padHexValue(asic_info_struct.market_name.decode("utf-8"), 4),
|
||||
"vendor_id": asic_info_struct.vendor_id,
|
||||
"vendor_name": asic_info_struct.vendor_name.decode("utf-8"),
|
||||
"subvendor_id": asic_info_struct.subvendor_id,
|
||||
"device_id": asic_info_struct.device_id,
|
||||
"rev_id": hex(asic_info_struct.rev_id),
|
||||
"rev_id": _padHexValue(hex(asic_info_struct.rev_id), 2),
|
||||
"asic_serial": asic_info_struct.asic_serial.decode("utf-8"),
|
||||
"oam_id": asic_info_struct.oam_id
|
||||
}
|
||||
@@ -1863,17 +1908,16 @@ def amdsmi_get_gpu_board_info(
|
||||
)
|
||||
|
||||
board_info_dict = {
|
||||
"model_number": board_info.model_number.decode("utf-8").strip(),
|
||||
"model_number": _padHexValue(board_info.model_number.decode("utf-8").strip(), 4),
|
||||
"product_serial": board_info.product_serial.decode("utf-8").strip(),
|
||||
"fru_id": board_info.fru_id.decode("utf-8").strip(),
|
||||
"product_name": board_info.product_name.decode("utf-8").strip(),
|
||||
"product_name": _padHexValue(board_info.product_name.decode("utf-8").strip(), 4),
|
||||
"manufacturer_name": board_info.manufacturer_name.decode("utf-8").strip()
|
||||
}
|
||||
|
||||
for key, value in board_info_dict.items():
|
||||
if value == "":
|
||||
board_info_dict[key] = "N/A"
|
||||
|
||||
return board_info_dict
|
||||
|
||||
|
||||
|
||||
@@ -882,7 +882,7 @@ class struct_amdsmi_asic_info_t(Structure):
|
||||
|
||||
struct_amdsmi_asic_info_t._pack_ = 1 # source:False
|
||||
struct_amdsmi_asic_info_t._fields_ = [
|
||||
('market_name', ctypes.c_char * 64),
|
||||
('market_name', ctypes.c_char * 256),
|
||||
('vendor_id', ctypes.c_uint32),
|
||||
('vendor_name', ctypes.c_char * 64),
|
||||
('subvendor_id', ctypes.c_uint32),
|
||||
@@ -961,11 +961,11 @@ class struct_amdsmi_board_info_t(Structure):
|
||||
|
||||
struct_amdsmi_board_info_t._pack_ = 1 # source:False
|
||||
struct_amdsmi_board_info_t._fields_ = [
|
||||
('model_number', ctypes.c_char * 32),
|
||||
('model_number', ctypes.c_char * 256),
|
||||
('product_serial', ctypes.c_char * 32),
|
||||
('fru_id', ctypes.c_char * 32),
|
||||
('product_name', ctypes.c_char * 128),
|
||||
('manufacturer_name', ctypes.c_char * 32),
|
||||
('product_name', ctypes.c_char * 256),
|
||||
('manufacturer_name', ctypes.c_char * 64),
|
||||
('reserved', ctypes.c_uint32 * 32),
|
||||
]
|
||||
|
||||
|
||||
@@ -3451,8 +3451,7 @@ rsmi_status_t rsmi_dev_process_isolation_set(uint32_t dv_ind,
|
||||
uint32_t pisolate);
|
||||
|
||||
/**
|
||||
* @brief Clear the GPU SRAM data
|
||||
*
|
||||
* @brief Clear the GPU SRAM data
|
||||
*
|
||||
* @details Given a device index @p dv_ind, this function will clear the
|
||||
* GPU SRAM data of this device. This can be called between user logins to prevent information leak.
|
||||
|
||||
@@ -45,14 +45,17 @@
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "rocm_smi/rocm_smi_device.h"
|
||||
|
||||
@@ -125,13 +128,33 @@ std::string print_rsmi_od_volt_freq_regions(uint32_t num_regions,
|
||||
bool is_sudo_user();
|
||||
rsmi_status_t rsmi_get_gfx_target_version(uint32_t dv_ind,
|
||||
std::string *gfx_version);
|
||||
|
||||
std::string leftTrim(const std::string &s);
|
||||
std::string rightTrim(const std::string &s);
|
||||
std::string trim(const std::string &s);
|
||||
std::string removeNewLines(const std::string &s);
|
||||
|
||||
std::string removeString(const std::string origStr,
|
||||
const std::string &removeMe);
|
||||
template <typename T>
|
||||
std::string print_int_as_hex(T i, bool showHexNotation = true) {
|
||||
std::string print_int_as_hex(T i, bool showHexNotation = true,
|
||||
int overloadBitSize = 0) {
|
||||
std::stringstream ss;
|
||||
if (showHexNotation) {
|
||||
ss << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex;
|
||||
if (overloadBitSize == 0) {
|
||||
ss << "0x" << std::hex << std::setw(sizeof(T) * 2) << std::setfill('0');
|
||||
} else {
|
||||
// 8 bits per 1 byte
|
||||
int byteSize = (overloadBitSize / 8) * 2;
|
||||
ss << "0x" << std::hex << std::setw(byteSize) << std::setfill('0');
|
||||
}
|
||||
} else {
|
||||
ss << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex;
|
||||
if (overloadBitSize == 0) {
|
||||
ss << std::hex << std::setw(sizeof(T) * 2) << std::setfill('0');
|
||||
} else {
|
||||
int byteSize = (overloadBitSize / 8) * 2;
|
||||
ss << std::hex << std::setw(byteSize) << std::setfill('0');
|
||||
}
|
||||
}
|
||||
|
||||
if (std::is_same<std::uint8_t, T>::value) {
|
||||
@@ -162,7 +185,8 @@ std::string print_unsigned_hex_and_int(T i, std::string heading="") {
|
||||
}
|
||||
ss << "Hex (MSB): " << print_int_as_hex(i) << ", "
|
||||
<< "Unsigned int: " << print_unsigned_int(i) << ", "
|
||||
<< "Byte Size: " << sizeof(T);
|
||||
<< "Byte Size: " << sizeof(T) << ", "
|
||||
<< "Bits: " << sizeof(T) * 8; // 8 bits per 1 byte
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -283,8 +307,298 @@ class ScopedAcquire {
|
||||
// In VM environment, the /proc/cpuinfo set hypervisor flag by default
|
||||
bool is_vm_guest();
|
||||
|
||||
// trim a string
|
||||
std::string trim(const std::string &s);
|
||||
|
||||
//
|
||||
enum class TagSplitterPositional_t
|
||||
{
|
||||
kFIRST,
|
||||
kBETWEEN,
|
||||
kLAST,
|
||||
kNONE,
|
||||
};
|
||||
|
||||
template <typename PrimaryKeyType = std::string, typename PrimaryDataType = std::string,
|
||||
typename SecondaryKeyType = PrimaryKeyType, typename SecondaryDataType = PrimaryDataType>
|
||||
class TagTextContents_t
|
||||
{
|
||||
public:
|
||||
using TextLines_t = std::vector<std::string>;
|
||||
using PrimaryList_t = std::vector<PrimaryDataType>;
|
||||
using SecondaryList_t = std::vector<SecondaryDataType>;
|
||||
using PrimaryKeyTbl_t = std::map<PrimaryKeyType, PrimaryList_t>;
|
||||
using SecondaryKeyTbl_t = std::map<SecondaryKeyType, SecondaryList_t>;
|
||||
using StructuredKeysTbl_t = std::map<PrimaryDataType, std::map<SecondaryKeyType, SecondaryDataType>>;
|
||||
|
||||
//
|
||||
TagTextContents_t() = default;
|
||||
TagTextContents_t(const TagTextContents_t&) = delete;
|
||||
TagTextContents_t(TagTextContents_t&&) = delete;
|
||||
TagTextContents_t& operator=(const TagTextContents_t&) = delete;
|
||||
TagTextContents_t& operator=(TagTextContents_t&&) = delete;
|
||||
|
||||
explicit TagTextContents_t(const TextLines_t& text_content)
|
||||
: m_text_content(text_content) {}
|
||||
|
||||
TagTextContents_t& set_text_content(const TextLines_t& text_content)
|
||||
{
|
||||
m_text_content = text_content;
|
||||
}
|
||||
|
||||
TagTextContents_t& set_title_terminator(const std::string& title_mark,
|
||||
TagSplitterPositional_t title_mark_position) {
|
||||
m_title_mark = title_mark;
|
||||
m_title_mark_position = title_mark_position;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TagTextContents_t& set_key_data_splitter(const std::string& line_splitter_mark,
|
||||
TagSplitterPositional_t line_mark_position) {
|
||||
m_line_splitter_mark = line_splitter_mark;
|
||||
m_line_mark_position = line_mark_position;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
TagTextContents_t& structure_content() {
|
||||
// Sanitizes the content.
|
||||
if (!m_text_content.empty()) {
|
||||
std::for_each(m_text_content.begin(), m_text_content.end(), trim);
|
||||
section_title_lookup();
|
||||
section_data_lookup();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
decltype(auto) get_title_size() {
|
||||
return m_primary.size();
|
||||
}
|
||||
|
||||
decltype(auto) get_structured_subkeys_size(const PrimaryKeyType& prim_key) {
|
||||
return m_structured[prim_key].size();
|
||||
}
|
||||
|
||||
decltype(auto) contains_title_key(const PrimaryKeyType& key) {
|
||||
return (m_primary.find(key) != m_primary.end());
|
||||
}
|
||||
|
||||
decltype(auto) contains_structured_key(const PrimaryKeyType& prim_key,
|
||||
const SecondaryKeyType& sec_key) {
|
||||
if (auto first_key_itr = m_structured.find(prim_key);
|
||||
first_key_itr != m_structured.end()) {
|
||||
if (auto sec_key_itr = first_key_itr->second.find(sec_key);
|
||||
sec_key_itr != first_key_itr->second.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
decltype(auto) get_structured_value_by_keys(const PrimaryKeyType& prim_key,
|
||||
const SecondaryKeyType& sec_key,
|
||||
bool is_value_id = true) {
|
||||
if (auto first_key_itr = m_structured.find(prim_key);
|
||||
first_key_itr != m_structured.end()) {
|
||||
if (auto sec_key_itr = first_key_itr->second.find(sec_key);
|
||||
sec_key_itr != first_key_itr->second.end()) {
|
||||
SecondaryDataType key_value{};
|
||||
if (is_value_id) {
|
||||
key_value = SecondaryDataType(sec_key_itr->first) + " ";
|
||||
}
|
||||
key_value += sec_key_itr->second;
|
||||
return key_value;
|
||||
}
|
||||
}
|
||||
|
||||
return SecondaryDataType{};
|
||||
}
|
||||
|
||||
decltype(auto) get_structured_data_subkey_by_position(const PrimaryKeyType& prim_key,
|
||||
uint32_t key_position) {
|
||||
auto key_counter = uint32_t(0);
|
||||
SecondaryKeyType data_key{};
|
||||
if (key_position < (get_structured_subkeys_size(prim_key))) {
|
||||
for (const auto& [sec_key, sec_value] : m_structured[prim_key]) {
|
||||
if (key_counter == key_position) {
|
||||
data_key = static_cast<SecondaryKeyType>(sec_key);
|
||||
return data_key;
|
||||
}
|
||||
++key_counter;
|
||||
}
|
||||
}
|
||||
|
||||
return data_key;
|
||||
}
|
||||
|
||||
decltype(auto) get_structured_data_subkey_first(const PrimaryKeyType& prim_key) {
|
||||
return (get_structured_value_by_keys(prim_key,
|
||||
get_structured_data_subkey_by_position(prim_key, 0)));
|
||||
}
|
||||
|
||||
decltype(auto) get_structured_data_subkey_last(const PrimaryKeyType& prim_key) {
|
||||
return (get_structured_value_by_keys(prim_key, get_structured_data_subkey_by_position(prim_key,
|
||||
(get_structured_subkeys_size(prim_key) - 1))));
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_text_content.clear();
|
||||
m_primary.clear();
|
||||
m_structured.clear();
|
||||
m_title_mark.clear();
|
||||
m_line_splitter_mark.clear();
|
||||
m_title_mark_position = TagSplitterPositional_t::kNONE;
|
||||
m_line_mark_position = TagSplitterPositional_t::kNONE;
|
||||
}
|
||||
|
||||
decltype(auto) dump_structured_content() {
|
||||
std::ostringstream ostrstream;
|
||||
ostrstream << __PRETTY_FUNCTION__ << "| ======= start =======" << "\n";
|
||||
ostrstream << "** Primary Table **" << "\n";
|
||||
for (const auto& [key, values] : m_primary) {
|
||||
ostrstream << "key: " << key << " values: " << values.size() << "\n";
|
||||
for (const auto& value : values) {
|
||||
ostrstream << "\t value: " << value << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
ostrstream << "\n ** Structured Table **" << "\n";
|
||||
for (const auto& [prim_key, prim_values] : m_structured) {
|
||||
ostrstream << "key: " << prim_key << "\n";
|
||||
for (const auto& [sec_key, sec_value] : prim_values) {
|
||||
ostrstream << "\t key: " << sec_key << " -> " << sec_value << "\n";
|
||||
}
|
||||
}
|
||||
ostrstream << "\n\n";
|
||||
|
||||
return ostrstream.str();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
TextLines_t m_text_content;
|
||||
PrimaryKeyTbl_t m_primary;
|
||||
StructuredKeysTbl_t m_structured;
|
||||
std::string m_title_mark;
|
||||
std::string m_line_splitter_mark;
|
||||
TagSplitterPositional_t m_title_mark_position;
|
||||
TagSplitterPositional_t m_line_mark_position;
|
||||
|
||||
//
|
||||
// Note: Organizes table with Title as a Key, and a list of values.
|
||||
//
|
||||
decltype(auto) section_title_lookup() {
|
||||
if (m_title_mark.empty() ||
|
||||
m_title_mark_position == TagSplitterPositional_t::kNONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Note:
|
||||
// - top_title_line: Left pointer for the sliding window
|
||||
// - bottom_title_line: Right pointer for the sliding window
|
||||
//
|
||||
auto top_title_line = uint32_t(std::numeric_limits<uint32_t>::max());
|
||||
auto bottom_title_line = uint32_t(std::numeric_limits<uint32_t>::max());
|
||||
auto line_counter = uint32_t(0);
|
||||
|
||||
//
|
||||
// Note: This whole interval/window where the section/title starts, and where it ends.
|
||||
//
|
||||
auto update_primary_tbl = [&](const uint32_t& from_line, const uint32_t& to_line) {
|
||||
auto key = static_cast<PrimaryKeyType>(m_text_content[from_line]);
|
||||
for (auto line_num(from_line + 1); line_num < to_line; ++line_num) {
|
||||
if ((line_num < m_text_content.size()) && !m_text_content[line_num].empty()) {
|
||||
m_primary[key].push_back(m_text_content[line_num]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto adjust_sliding_window = [&](const uint32_t& title_line) {
|
||||
// First time top_title_line gets adjusted.
|
||||
if (top_title_line == uint32_t(std::numeric_limits<uint32_t>::max())) {
|
||||
top_title_line = title_line;
|
||||
bottom_title_line = top_title_line;
|
||||
return;
|
||||
}
|
||||
if (title_line > bottom_title_line) {
|
||||
bottom_title_line = title_line;
|
||||
update_primary_tbl(top_title_line, bottom_title_line);
|
||||
top_title_line = bottom_title_line;
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto& line : m_text_content) {
|
||||
auto was_title_found{false};
|
||||
switch (m_title_mark_position) {
|
||||
case TagSplitterPositional_t::kFIRST:
|
||||
// Section/Title Mark was found at the first position
|
||||
if (line.find_first_of(m_title_mark.c_str()) == 0) {
|
||||
was_title_found = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case TagSplitterPositional_t::kLAST:
|
||||
// Section/Title Mark was found at the last position
|
||||
if ((line.find_last_of(m_title_mark.c_str()) + 1) == line.size()) {
|
||||
was_title_found = true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (was_title_found) {
|
||||
adjust_sliding_window(line_counter);
|
||||
}
|
||||
++line_counter;
|
||||
}
|
||||
|
||||
// Any remaining elements? If so, the data belongs to the last found section title
|
||||
if (line_counter > bottom_title_line) {
|
||||
update_primary_tbl(bottom_title_line, line_counter);
|
||||
}
|
||||
}
|
||||
|
||||
decltype(auto) section_data_lookup() {
|
||||
if (m_line_splitter_mark.empty() ||
|
||||
m_line_mark_position == TagSplitterPositional_t::kNONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Note: Organizes table with Title as a Key, a Key/ID for values and values.
|
||||
// It takes into consideration the initial constraints were all good and
|
||||
// that the primary table has been populated.
|
||||
auto sec_key = std::string();
|
||||
auto sec_data = std::string();
|
||||
auto auto_key = uint32_t(0);
|
||||
for (const auto& [prim_key, prim_values] : m_primary) {
|
||||
for (const auto& value : prim_values) {
|
||||
if (auto mark_pos = value.find_first_of(m_line_splitter_mark.c_str());
|
||||
mark_pos != std::string::npos) {
|
||||
sec_key = trim(value.substr(0, mark_pos + 1));
|
||||
sec_data = trim(value.substr((mark_pos + 1), value.size()));
|
||||
}
|
||||
// In case there is no 'key' based on the data token marker, generate one.
|
||||
else {
|
||||
sec_key = std::to_string(auto_key) + m_line_splitter_mark;
|
||||
sec_data = trim(value.substr(0, value.size()));
|
||||
++auto_key;
|
||||
}
|
||||
if (!sec_key.empty()) {
|
||||
m_structured[prim_key].insert(std::make_pair(sec_key, sec_data));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using TextFileTagContents_t = TagTextContents_t<std::string, std::string,
|
||||
std::string, std::string>;
|
||||
|
||||
|
||||
} // namespace smi
|
||||
} // namespace amd
|
||||
|
||||
@@ -1415,17 +1415,6 @@ For the new format, GFXCLK field will show min and max values(0/1). If the curre
|
||||
frequency in neither min/max but lies within the range, this is indicated by
|
||||
an additional value followed by * at index 1 and max value at index 2.
|
||||
*/
|
||||
constexpr uint32_t kOD_SCLK_label_array_index = 0;
|
||||
constexpr uint32_t kOD_MCLK_label_array_index =
|
||||
kOD_SCLK_label_array_index + 3;
|
||||
constexpr uint32_t kOD_VDDC_CURVE_label_array_index =
|
||||
kOD_MCLK_label_array_index + 2;
|
||||
constexpr uint32_t kOD_OD_RANGE_label_array_index =
|
||||
kOD_VDDC_CURVE_label_array_index + 4;
|
||||
constexpr uint32_t kOD_VDDC_CURVE_start_index =
|
||||
kOD_OD_RANGE_label_array_index + 3;
|
||||
// constexpr uint32_t kOD_VDDC_CURVE_num_lines =
|
||||
// kOD_VDDC_CURVE_start_index + 4;
|
||||
constexpr uint32_t kMIN_VALID_LINES = 2;
|
||||
|
||||
static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind,
|
||||
@@ -1450,62 +1439,95 @@ static rsmi_status_t get_od_clk_volt_info(uint32_t dv_ind,
|
||||
return RSMI_STATUS_NOT_YET_IMPLEMENTED;
|
||||
}
|
||||
|
||||
assert(val_vec[kOD_SCLK_label_array_index] == "OD_SCLK:" ||
|
||||
val_vec[kOD_SCLK_label_array_index] == "GFXCLK:");
|
||||
if ((val_vec[kOD_SCLK_label_array_index] != "OD_SCLK:") &&
|
||||
(val_vec[kOD_SCLK_label_array_index] != "GFXCLK:")) {
|
||||
return RSMI_STATUS_UNEXPECTED_DATA;
|
||||
// Tags expected in this file
|
||||
const std::string kTAG_OD_SCLK{"OD_SCLK:"};
|
||||
const std::string KTAG_OD_MCLK{"OD_MCLK:"};
|
||||
const std::string kTAG_GFXCLK{"GFXCLK:"};
|
||||
const std::string KTAG_MCLK{"MCLK:"};
|
||||
const std::string KTAG_SCLK{"SCLK:"};
|
||||
const std::string KTAG_OD_RANGE{"OD_RANGE:"};
|
||||
const std::string KTAG_OD_VDDGFX_OFFSET{"OD_VDDGFX_OFFSET:"};
|
||||
const std::string KTAG_FIRST_FREQ_IDX{"0:"};
|
||||
|
||||
amd::smi::TextFileTagContents_t txt_power_dev_od_voltage(val_vec);
|
||||
txt_power_dev_od_voltage
|
||||
.set_title_terminator(":", amd::smi::TagSplitterPositional_t::kLAST)
|
||||
.set_key_data_splitter(":", amd::smi::TagSplitterPositional_t::kBETWEEN)
|
||||
.structure_content();
|
||||
|
||||
//
|
||||
// Note: We must have minimum of 'GFXCLK:' && 'MCLK:' OR:
|
||||
// 'OD_SCLK:' && 'OD_MCLK:' tags.
|
||||
if (txt_power_dev_od_voltage.get_title_size() < kMIN_VALID_LINES) {
|
||||
return rsmi_status_t::RSMI_STATUS_NO_DATA;
|
||||
}
|
||||
|
||||
|
||||
// find last_item but skip empty lines
|
||||
int last_item = val_vec.size()-1;
|
||||
while (val_vec[last_item].empty() || val_vec[last_item][0] == 0)
|
||||
last_item--;
|
||||
|
||||
p->curr_sclk_range.lower_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_SCLK_label_array_index + 1);
|
||||
p->curr_sclk_range.upper_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_SCLK_label_array_index + 2);
|
||||
|
||||
if (val_vec.size() < (kOD_MCLK_label_array_index + 1)) {
|
||||
return RSMI_STATUS_UNEXPECTED_SIZE;
|
||||
}
|
||||
// The condition below checks if it is the old style or new style format.
|
||||
if (val_vec[kOD_MCLK_label_array_index] == "OD_MCLK:") {
|
||||
p->curr_mclk_range.lower_bound = 0;
|
||||
p->curr_mclk_range.upper_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_MCLK_label_array_index + 1);
|
||||
} else if (val_vec[kOD_MCLK_label_array_index] == "MCLK:") {
|
||||
p->curr_mclk_range.lower_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_MCLK_label_array_index + 1);
|
||||
// the upper memory frequency is the last
|
||||
p->curr_mclk_range.upper_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, last_item);
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
} else {
|
||||
if (val_vec.size() < (kOD_MCLK_label_array_index + 3)) {
|
||||
return RSMI_STATUS_UNEXPECTED_SIZE;
|
||||
}
|
||||
if (val_vec[kOD_MCLK_label_array_index + 1] == "MCLK:") {
|
||||
p->curr_sclk_range.upper_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_SCLK_label_array_index + 3);
|
||||
p->curr_mclk_range.lower_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, kOD_MCLK_label_array_index + 2);
|
||||
// the upper memory frequency is the last
|
||||
p->curr_mclk_range.upper_bound = freq_string_to_int(val_vec, nullptr,
|
||||
nullptr, last_item);
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
}
|
||||
return RSMI_STATUS_NOT_YET_IMPLEMENTED;
|
||||
// Note: For debug builds/purposes only.
|
||||
assert(txt_power_dev_od_voltage.contains_title_key(kTAG_GFXCLK) ||
|
||||
txt_power_dev_od_voltage.contains_title_key(kTAG_OD_SCLK));
|
||||
// Note: For release builds/purposes.
|
||||
if (!txt_power_dev_od_voltage.contains_title_key(kTAG_GFXCLK) &&
|
||||
!txt_power_dev_od_voltage.contains_title_key(kTAG_OD_SCLK)) {
|
||||
return rsmi_status_t::RSMI_STATUS_UNEXPECTED_DATA;
|
||||
}
|
||||
|
||||
if (val_vec.size() < kOD_VDDC_CURVE_label_array_index) {
|
||||
return RSMI_STATUS_UNEXPECTED_SIZE;
|
||||
// Note: Quick helpers for getting 1st and last elements found
|
||||
auto build_lower_bound = [&](const std::string& prim_key) {
|
||||
auto lower_bound_data = txt_power_dev_od_voltage.get_structured_data_subkey_first(prim_key);
|
||||
return std::vector<std::string>{lower_bound_data};
|
||||
};
|
||||
|
||||
auto build_upper_bound = [&](const std::string& prim_key) {
|
||||
auto upper_bound_data = txt_power_dev_od_voltage.get_structured_data_subkey_last(prim_key);
|
||||
return std::vector<std::string>{upper_bound_data};
|
||||
};
|
||||
|
||||
// Validates 'OD_SCLK' is in the structure
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(kTAG_OD_SCLK,
|
||||
KTAG_FIRST_FREQ_IDX)) {
|
||||
p->curr_sclk_range.lower_bound = freq_string_to_int(build_lower_bound(kTAG_OD_SCLK), nullptr, nullptr, 0);
|
||||
p->curr_sclk_range.upper_bound = freq_string_to_int(build_upper_bound(kTAG_OD_SCLK), nullptr, nullptr, 0);
|
||||
|
||||
// Validates 'OD_MCLK' is in the structure
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_MCLK,
|
||||
KTAG_FIRST_FREQ_IDX)) {
|
||||
p->curr_mclk_range.lower_bound = freq_string_to_int(build_lower_bound(KTAG_OD_MCLK), nullptr, nullptr, 0);
|
||||
p->curr_mclk_range.upper_bound = freq_string_to_int(build_upper_bound(KTAG_OD_MCLK), nullptr, nullptr, 0);
|
||||
}
|
||||
|
||||
// Validates 'OD_RANGE' is in the structure
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
|
||||
KTAG_SCLK)) {
|
||||
od_value_pair_str_to_range(txt_power_dev_od_voltage
|
||||
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_SCLK),
|
||||
&p->sclk_freq_limits);
|
||||
}
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
|
||||
KTAG_MCLK)) {
|
||||
od_value_pair_str_to_range(txt_power_dev_od_voltage
|
||||
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_MCLK),
|
||||
&p->mclk_freq_limits);
|
||||
}
|
||||
}
|
||||
// Validates 'GFXCLK' is in the structure
|
||||
else if (txt_power_dev_od_voltage.contains_structured_key(kTAG_GFXCLK,
|
||||
KTAG_FIRST_FREQ_IDX)) {
|
||||
p->curr_sclk_range.lower_bound = freq_string_to_int(build_lower_bound(kTAG_GFXCLK), nullptr, nullptr, 0);
|
||||
p->curr_sclk_range.upper_bound = freq_string_to_int(build_upper_bound(kTAG_GFXCLK), nullptr, nullptr, 0);
|
||||
|
||||
// Validates 'MCLK' is in the structure
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_MCLK,
|
||||
KTAG_FIRST_FREQ_IDX)) {
|
||||
p->curr_mclk_range.lower_bound = freq_string_to_int(build_lower_bound(KTAG_MCLK), nullptr, nullptr, 0);
|
||||
p->curr_mclk_range.upper_bound = freq_string_to_int(build_upper_bound(KTAG_MCLK), nullptr, nullptr, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return RSMI_STATUS_NOT_YET_IMPLEMENTED;
|
||||
}
|
||||
|
||||
p->num_regions =
|
||||
static_cast<uint32_t>((val_vec.size()) / 2);
|
||||
// Note: No curve entries.
|
||||
p->num_regions = 0;
|
||||
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
CATCH
|
||||
@@ -1674,28 +1696,34 @@ rsmi_status_t rsmi_dev_od_volt_info_set(uint32_t dv_ind, uint32_t vpoint,
|
||||
}
|
||||
|
||||
|
||||
static void get_vc_region(uint32_t start_ind,
|
||||
std::vector<std::string> *val_vec, rsmi_freq_volt_region_t *p) {
|
||||
static void get_vc_region(const std::vector<std::string>& val_vec, rsmi_freq_volt_region_t& p)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << __PRETTY_FUNCTION__ << " | ======= start =======";
|
||||
LOG_TRACE(ss);
|
||||
assert(p != nullptr);
|
||||
assert(val_vec != nullptr);
|
||||
THROW_IF_NULLPTR_DEREF(p)
|
||||
THROW_IF_NULLPTR_DEREF(val_vec)
|
||||
|
||||
// There must be at least 1 region to read in
|
||||
assert(val_vec->size() >= kOD_OD_RANGE_label_array_index + 2);
|
||||
assert((*val_vec)[kOD_OD_RANGE_label_array_index] == "OD_RANGE:");
|
||||
if ((val_vec->size() < kOD_OD_RANGE_label_array_index + 2) ||
|
||||
((*val_vec)[kOD_OD_RANGE_label_array_index] != "OD_RANGE:") ) {
|
||||
ss << __PRETTY_FUNCTION__ << " | ======= end ======= | returning "
|
||||
<< getRSMIStatusString(RSMI_STATUS_UNEXPECTED_DATA);
|
||||
LOG_TRACE(ss);
|
||||
throw amd::smi::rsmi_exception(RSMI_STATUS_UNEXPECTED_DATA, __FUNCTION__);
|
||||
//
|
||||
amd::smi::TextFileTagContents_t txt_power_dev_od_voltage(val_vec);
|
||||
txt_power_dev_od_voltage
|
||||
.set_title_terminator(":", amd::smi::TagSplitterPositional_t::kLAST)
|
||||
.set_key_data_splitter(":", amd::smi::TagSplitterPositional_t::kBETWEEN)
|
||||
.structure_content();
|
||||
|
||||
const std::string KTAG_OD_RANGE{"OD_RANGE:"};
|
||||
const std::string KTAG_MCLK{"MCLK:"};
|
||||
const std::string KTAG_SCLK{"SCLK:"};
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
|
||||
KTAG_SCLK)) {
|
||||
od_value_pair_str_to_range(txt_power_dev_od_voltage
|
||||
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_SCLK),
|
||||
&p.freq_range);
|
||||
}
|
||||
if (txt_power_dev_od_voltage.contains_structured_key(KTAG_OD_RANGE,
|
||||
KTAG_MCLK)) {
|
||||
od_value_pair_str_to_range(txt_power_dev_od_voltage
|
||||
.get_structured_value_by_keys(KTAG_OD_RANGE, KTAG_MCLK),
|
||||
&p.volt_range);
|
||||
}
|
||||
od_value_pair_str_to_range((*val_vec)[start_ind], &p->freq_range);
|
||||
od_value_pair_str_to_range((*val_vec)[start_ind + 1], &p->volt_range);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1729,23 +1757,24 @@ static rsmi_status_t get_od_clk_volt_curve_regions(uint32_t dv_ind,
|
||||
|
||||
// This is a work-around to handle systems where kDevPowerODVoltage is not
|
||||
// fully supported yet.
|
||||
if (val_vec.size() < 2) {
|
||||
if (val_vec.size() < kMIN_VALID_LINES) {
|
||||
ss << __PRETTY_FUNCTION__
|
||||
<< " | Issue: val_vec.size() < 2" << "; returning "
|
||||
<< " | Issue: val_vec.size() < " << kMIN_VALID_LINES << "; returning "
|
||||
<< getRSMIStatusString(RSMI_STATUS_NOT_YET_IMPLEMENTED);
|
||||
LOG_ERROR(ss);
|
||||
return RSMI_STATUS_NOT_YET_IMPLEMENTED;
|
||||
}
|
||||
|
||||
uint32_t val_vec_size = static_cast<uint32_t>(val_vec.size());
|
||||
assert((val_vec_size - kOD_VDDC_CURVE_start_index) > 0);
|
||||
|
||||
ss << __PRETTY_FUNCTION__
|
||||
<< " | val_vec_size = " << std::dec
|
||||
<< val_vec_size
|
||||
<< " | kOD_VDDC_CURVE_start_index = " << kOD_VDDC_CURVE_start_index;
|
||||
<< val_vec_size;
|
||||
LOG_DEBUG(ss);
|
||||
*num_regions = std::min((val_vec_size) / 2, *num_regions);
|
||||
|
||||
// Note: No curve entries.
|
||||
*num_regions = 0;
|
||||
// Get OD ranges.
|
||||
get_vc_region(val_vec, *p);
|
||||
|
||||
return RSMI_STATUS_SUCCESS;
|
||||
CATCH
|
||||
|
||||
@@ -707,6 +707,8 @@ static bool isAMDGPU(std::string dev_path) {
|
||||
uint32_t RocmSMI::DiscoverAmdgpuDevices(void) {
|
||||
std::string err_msg;
|
||||
uint32_t count = 0;
|
||||
int32_t cardId = 0;
|
||||
int32_t max_cardId = -1;
|
||||
std::ostringstream ss;
|
||||
|
||||
// If this gets called more than once, clear previous findings.
|
||||
@@ -730,6 +732,9 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) {
|
||||
if ((strcmp(dentry->d_name, ".") == 0) ||
|
||||
(strcmp(dentry->d_name, "..") == 0))
|
||||
continue;
|
||||
sscanf(&dentry->d_name[strlen(kDeviceNamePrefix)], "%d", &cardId);
|
||||
if (cardId > max_cardId)
|
||||
max_cardId = cardId;
|
||||
count++;
|
||||
}
|
||||
dentry = readdir(drm_dir);
|
||||
@@ -782,7 +787,7 @@ uint32_t RocmSMI::DiscoverAmdgpuDevices(void) {
|
||||
|
||||
uint32_t cardAdded = 0;
|
||||
// Discover all root cards & gpu partitions associated with each
|
||||
for (uint32_t cardId = 0; cardId < count; cardId++) {
|
||||
for (uint32_t cardId = 0; cardId <= max_cardId; cardId++) {
|
||||
std::string path = kPathDRMRoot;
|
||||
path += "/card";
|
||||
path += std::to_string(cardId);
|
||||
|
||||
@@ -1140,7 +1140,7 @@ std::string print_rsmi_od_volt_freq_data_t(rsmi_od_volt_freq_data_t *odv) {
|
||||
&odv->mclk_freq_limits);
|
||||
|
||||
ss << "\t**Current Freq/Volt. curve: " << "\n";
|
||||
ss << pt_vddc_curve(&odv->curve);
|
||||
ss << "\t\t N/A" << "\n";
|
||||
|
||||
ss << "\t**Number of Freq./Volt. regions: " << odv->num_regions << "\n\n";
|
||||
return ss.str();
|
||||
@@ -1224,5 +1224,6 @@ std::queue<std::string> getAllDeviceGfxVers() {
|
||||
return deviceGfxVersions;
|
||||
}
|
||||
|
||||
|
||||
} // namespace smi
|
||||
} // namespace amd
|
||||
|
||||
@@ -389,7 +389,6 @@ amdsmi_get_gpu_device_bdf(amdsmi_processor_handle processor_handle, amdsmi_bdf_t
|
||||
}
|
||||
|
||||
amdsmi_status_t amdsmi_get_gpu_board_info(amdsmi_processor_handle processor_handle, amdsmi_board_info_t *board_info) {
|
||||
|
||||
AMDSMI_CHECK_INIT();
|
||||
|
||||
if (board_info == nullptr) {
|
||||
@@ -405,17 +404,86 @@ amdsmi_status_t amdsmi_get_gpu_board_info(amdsmi_processor_handle processor_hand
|
||||
if (gpu_device->check_if_drm_is_supported()) {
|
||||
// Populate product_serial, product_name, & product_number from sysfs
|
||||
status = smi_amdgpu_get_board_info(gpu_device, board_info);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// ignore the errors so that it can populate as many fields as possible.
|
||||
// call rocm-smi which search multiple places for device name
|
||||
status = rsmi_wrapper(rsmi_dev_name_get, processor_handle,
|
||||
board_info->product_name, AMDSMI_PRODUCT_NAME_LENGTH);
|
||||
board_info->product_name, AMDSMI_256_LENGTH);
|
||||
|
||||
status = rsmi_wrapper(rsmi_dev_serial_number_get, processor_handle,
|
||||
board_info->product_serial, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
}
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << __PRETTY_FUNCTION__ << "[Before rocm smi correction] "
|
||||
<< "Returning status = AMDSMI_STATUS_SUCCESS"
|
||||
<< "\n; info->model_number: |" << board_info->model_number << "|"
|
||||
<< "\n; info->product_serial: |" << board_info->product_serial << "|"
|
||||
<< "\n; info->fru_id: |" << board_info->fru_id << "|"
|
||||
<< "\n; info->manufacturer_name: |" << board_info->manufacturer_name << "|"
|
||||
<< "\n; info->product_name: |" << board_info->product_name << "|";
|
||||
LOG_INFO(ss);
|
||||
|
||||
// Correct any missing details
|
||||
if (board_info->model_number[0] == '\0') {
|
||||
status = rsmi_wrapper(rsmi_dev_name_get, processor_handle, board_info->model_number,
|
||||
AMDSMI_256_LENGTH);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
memset(board_info->model_number, 0,
|
||||
AMDSMI_256_LENGTH * sizeof(board_info->model_number[0]));
|
||||
}
|
||||
ss << __PRETTY_FUNCTION__ << " | [rsmi_correction] board_info->model_number= |"
|
||||
<< board_info->model_number << "|";
|
||||
LOG_INFO(ss);
|
||||
}
|
||||
|
||||
if (board_info->product_serial[0] == '\0') {
|
||||
status = rsmi_wrapper(rsmi_dev_serial_number_get, processor_handle,
|
||||
board_info->product_serial, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
memset(board_info->product_serial, 0,
|
||||
AMDSMI_NORMAL_STRING_LENGTH * sizeof(board_info->product_serial[0]));
|
||||
}
|
||||
ss << __PRETTY_FUNCTION__ << " | [rsmi_correction] board_info->product_serial= |"
|
||||
<< board_info->product_serial << "|";
|
||||
LOG_INFO(ss);
|
||||
}
|
||||
|
||||
if (board_info->product_name[0] == '\0') {
|
||||
status = rsmi_wrapper(rsmi_dev_subsystem_name_get,
|
||||
processor_handle, board_info->product_name,
|
||||
AMDSMI_256_LENGTH);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
memset(board_info->product_name, 0,
|
||||
AMDSMI_256_LENGTH * sizeof(board_info->product_name[0]));
|
||||
}
|
||||
ss << __PRETTY_FUNCTION__ << " | [rsmi_correction] board_info->product_name= |"
|
||||
<< board_info->product_name << "|";
|
||||
LOG_INFO(ss);
|
||||
}
|
||||
|
||||
if (board_info->manufacturer_name[0] == '\0') {
|
||||
status = rsmi_wrapper(rsmi_dev_vendor_name_get,
|
||||
processor_handle, board_info->manufacturer_name,
|
||||
AMDSMI_MAX_STRING_LENGTH);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
memset(board_info->manufacturer_name, 0,
|
||||
AMDSMI_MAX_STRING_LENGTH * sizeof(board_info->manufacturer_name[0]));
|
||||
}
|
||||
ss << __PRETTY_FUNCTION__ << " | [rsmi_correction] board_info->manufacturer_name= |"
|
||||
<< board_info->manufacturer_name << "|";
|
||||
LOG_INFO(ss);
|
||||
}
|
||||
|
||||
ss << __PRETTY_FUNCTION__ << "[After rocm smi correction] "
|
||||
<< "Returning status = AMDSMI_STATUS_SUCCESS"
|
||||
<< "\n; info->model_number: |" << board_info->model_number << "|"
|
||||
<< "\n; info->product_serial: |" << board_info->product_serial << "|"
|
||||
<< "\n; info->fru_id: |" << board_info->fru_id << "|"
|
||||
<< "\n; info->manufacturer_name: |" << board_info->manufacturer_name << "|"
|
||||
<< "\n; info->product_name: |" << board_info->product_name << "|";
|
||||
LOG_INFO(ss);
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -654,7 +722,7 @@ amdsmi_get_gpu_asic_info(amdsmi_processor_handle processor_handle, amdsmi_asic_i
|
||||
status = smi_amdgpu_get_market_name_from_dev_id(dev_info.device_id, info->market_name);
|
||||
if (status != AMDSMI_STATUS_SUCCESS) {
|
||||
rsmi_wrapper(rsmi_dev_brand_get, processor_handle,
|
||||
info->market_name, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
info->market_name, AMDSMI_256_LENGTH);
|
||||
}
|
||||
|
||||
info->device_id = dev_info.device_id;
|
||||
@@ -667,7 +735,7 @@ amdsmi_get_gpu_asic_info(amdsmi_processor_handle processor_handle, amdsmi_asic_i
|
||||
if (status == AMDSMI_STATUS_SUCCESS) snprintf(info->asic_serial, sizeof(info->asic_serial), "%lu", dv_uid);
|
||||
|
||||
status = rsmi_wrapper(rsmi_dev_brand_get, processor_handle,
|
||||
info->market_name, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
info->market_name, AMDSMI_256_LENGTH);
|
||||
|
||||
status = rsmi_wrapper(rsmi_dev_vendor_id_get, processor_handle,
|
||||
&vendor_id);
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
#include <sys/ioctl.h>
|
||||
#include <algorithm>
|
||||
#include <limits.h>
|
||||
@@ -45,6 +47,69 @@
|
||||
#include "shared_mutex.h" // NOLINT
|
||||
#include "rocm_smi/rocm_smi_logger.h"
|
||||
|
||||
std::string leftTrim(const std::string &s) {
|
||||
if (!s.empty()) {
|
||||
return std::regex_replace(s, std::regex("^\\s+"), "");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string rightTrim(const std::string &s) {
|
||||
if (!s.empty()) {
|
||||
return std::regex_replace(s, std::regex("\\s+$"), "");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string removeNewLines(const std::string &s) {
|
||||
if (!s.empty()) {
|
||||
return std::regex_replace(s, std::regex("\n+"), "");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string trim(const std::string &s) {
|
||||
if (!s.empty()) {
|
||||
// remove new lines -> trim white space at ends
|
||||
std::string noNewLines = removeNewLines(s);
|
||||
return leftTrim(rightTrim(noNewLines));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Given original string and string to remove (removeMe)
|
||||
// Return will provide the resulting modified string with the removed string(s)
|
||||
std::string removeString(const std::string origStr,
|
||||
const std::string &removeMe) {
|
||||
std::string modifiedStr = origStr;
|
||||
std::string::size_type l = removeMe.length();
|
||||
for (std::string::size_type i = modifiedStr.find(removeMe);
|
||||
i != std::string::npos;
|
||||
i = modifiedStr.find(removeMe)) {
|
||||
modifiedStr.erase(i, l);
|
||||
}
|
||||
return modifiedStr;
|
||||
}
|
||||
|
||||
void openFileAndModifyBuffer(std::string path, char *buff, size_t sizeOfBuff) {
|
||||
bool errorDiscovered = false;
|
||||
std::ifstream file(path, std::ifstream::in);
|
||||
std::string contents = {std::istreambuf_iterator<char>{file}, std::istreambuf_iterator<char>{}};
|
||||
memset(buff, 0, sizeof(char) * sizeOfBuff);
|
||||
if (!file.is_open()) {
|
||||
errorDiscovered = true;
|
||||
} else {
|
||||
contents = trim(contents);
|
||||
}
|
||||
|
||||
file.close();
|
||||
if (!errorDiscovered && file.good() && !file.bad() && !file.fail() && !file.eof()
|
||||
&& !contents.empty()) {
|
||||
std::strncpy(buff, contents.c_str(), sizeOfBuff-1);
|
||||
buff[sizeOfBuff-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static const uint32_t kAmdGpuId = 0x1002;
|
||||
|
||||
static bool isAMDGPU(std::string dev_path) {
|
||||
@@ -123,50 +188,26 @@ amdsmi_status_t smi_amdgpu_get_board_info(amd::smi::AMDSmiGPUDevice* device, amd
|
||||
std::string manufacturer_name_path = "/sys/class/drm/" + device->get_gpu_path() + std::string("/device/manufacturer");
|
||||
std::string product_name_path = "/sys/class/drm/" + device->get_gpu_path() + std::string("/device/product_name");
|
||||
|
||||
FILE *fp;
|
||||
openFileAndModifyBuffer(model_number_path, info->model_number, AMDSMI_256_LENGTH);
|
||||
openFileAndModifyBuffer(product_serial_path, info->product_serial, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
openFileAndModifyBuffer(fru_id_path, info->fru_id, AMDSMI_NORMAL_STRING_LENGTH);
|
||||
openFileAndModifyBuffer(manufacturer_name_path, info->manufacturer_name,
|
||||
AMDSMI_MAX_STRING_LENGTH);
|
||||
openFileAndModifyBuffer(product_name_path, info->product_name, AMDSMI_256_LENGTH);
|
||||
|
||||
fp = fopen(model_number_path.c_str(), "rb");
|
||||
if (fp) {
|
||||
fgets(info->model_number, sizeof(info->model_number), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(product_serial_path.c_str(), "rb");
|
||||
if (fp) {
|
||||
fgets(info->product_serial, sizeof(info->product_serial), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(fru_id_path.c_str(), "rb");
|
||||
if (fp) {
|
||||
fgets(info->fru_id, sizeof(info->fru_id), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(manufacturer_name_path.c_str(), "rb");
|
||||
if (fp) {
|
||||
fgets(info->manufacturer_name, sizeof(info->manufacturer_name), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
fp = fopen(product_name_path.c_str(), "rb");
|
||||
if (fp) {
|
||||
fgets(info->product_name, sizeof(info->product_name), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
std::ostringstream ss;
|
||||
ss << __PRETTY_FUNCTION__
|
||||
ss << __PRETTY_FUNCTION__ << "[Before correction] "
|
||||
<< "Returning status = AMDSMI_STATUS_SUCCESS"
|
||||
<< " | model_number_path = " << model_number_path
|
||||
<< "; info->model_number: " << info->model_number
|
||||
<< "\n product_serial_path = " << product_serial_path
|
||||
<< "; info->product_serial: " << info->product_serial
|
||||
<< "\n fru_id_path = " << fru_id_path
|
||||
<< "; info->fru_id: " << info->fru_id
|
||||
<< "\n manufacturer_name_path = " << manufacturer_name_path
|
||||
<< "; info->manufacturer_name: " << info->manufacturer_name
|
||||
<< "\n product_name_path = " << product_name_path
|
||||
<< "; info->product_name: " << info->product_name;
|
||||
<< " | model_number_path = |" << model_number_path << "|\n"
|
||||
<< "; info->model_number: |" << info->model_number << "|\n"
|
||||
<< "\n product_serial_path = |" << product_serial_path << "|\n"
|
||||
<< "; info->product_serial: |" << info->product_serial << "|\n"
|
||||
<< "\n fru_id_path = |" << fru_id_path << "|\n"
|
||||
<< "; info->fru_id: |" << info->fru_id << "|\n"
|
||||
<< "\n manufacturer_name_path = |" << manufacturer_name_path << "|\n"
|
||||
<< "; info->manufacturer_name: |" << info->manufacturer_name << "|\n"
|
||||
<< "\n product_name_path = |" << product_name_path << "|\n"
|
||||
<< "; info->product_name: |" << info->product_name << "|";
|
||||
LOG_INFO(ss);
|
||||
|
||||
return AMDSMI_STATUS_SUCCESS;
|
||||
|
||||
@@ -64,7 +64,7 @@ $BLACKLIST_ALL_ASICS\
|
||||
# /sys/class/kfd/kfd/topology/nodes/*/properties
|
||||
FILTER[90400]=\
|
||||
$BLACKLIST_ALL_ASICS\
|
||||
"amdsmitstReadOnly.TestVoltCurvRead"
|
||||
# "amdsmitstReadOnly.TestVoltCurvRead"
|
||||
FILTER[90401]=${FILTER[90400]}
|
||||
FILTER[90402]=${FILTER[90400]}
|
||||
|
||||
|
||||
@@ -183,10 +183,10 @@ void TestMutualExclusion::Run(void) {
|
||||
int64_t dmy_i64 = 0;
|
||||
char dmy_str[10];
|
||||
amdsmi_dev_perf_level_t dmy_perf_lvl;
|
||||
amdsmi_frequencies_t dmy_freqs;
|
||||
amdsmi_od_volt_freq_data_t dmy_od_volt;
|
||||
amdsmi_freq_volt_region_t dmy_vlt_reg;
|
||||
amdsmi_error_count_t dmy_err_cnt;
|
||||
amdsmi_frequencies_t dmy_freqs{};
|
||||
amdsmi_od_volt_freq_data_t dmy_od_volt{};
|
||||
amdsmi_freq_volt_region_t dmy_vlt_reg{};
|
||||
amdsmi_error_count_t dmy_err_cnt{};
|
||||
amdsmi_ras_err_state_t dmy_ras_err_st;
|
||||
|
||||
// This can be replaced with ASSERT_EQ() once env. stabilizes
|
||||
|
||||
@@ -92,9 +92,9 @@ void TestPerfDeterminism::Close() {
|
||||
void TestPerfDeterminism::Run(void) {
|
||||
amdsmi_status_t err;
|
||||
amdsmi_dev_perf_level_t pfl;
|
||||
amdsmi_od_volt_freq_data_t odv;
|
||||
amdsmi_od_volt_freq_data_t odv{};
|
||||
amdsmi_status_t ret;
|
||||
uint64_t clkvalue;
|
||||
uint64_t clkvalue(0);
|
||||
TestBase::Run();
|
||||
if (setup_failed_) {
|
||||
std::cout << "** SetUp Failed for this test. Skipping.**" << std::endl;
|
||||
|
||||
@@ -146,7 +146,7 @@ static void print_amdsmi_od_volt_freq_regions(uint32_t num_regions,
|
||||
|
||||
void TestVoltCurvRead::Run(void) {
|
||||
amdsmi_status_t err;
|
||||
amdsmi_od_volt_freq_data_t odv;
|
||||
amdsmi_od_volt_freq_data_t odv{};
|
||||
|
||||
TestBase::Run();
|
||||
if (setup_failed_) {
|
||||
@@ -172,7 +172,6 @@ void TestVoltCurvRead::Run(void) {
|
||||
ASSERT_EQ(err, AMDSMI_STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
} else {
|
||||
CHK_ERR_ASRT(err)
|
||||
// Verify api support checking functionality is working
|
||||
err = amdsmi_get_gpu_od_volt_info(processor_handles_[i], nullptr);
|
||||
ASSERT_EQ(err, AMDSMI_STATUS_INVAL);
|
||||
@@ -182,15 +181,37 @@ void TestVoltCurvRead::Run(void) {
|
||||
std::cout << "\t**Frequency-voltage curve data:" << std::endl;
|
||||
print_amdsmi_od_volt_freq_data_t(&odv);
|
||||
|
||||
amdsmi_freq_volt_region_t *regions;
|
||||
amdsmi_freq_volt_region_t *regions{};
|
||||
uint32_t num_regions;
|
||||
regions = new amdsmi_freq_volt_region_t[odv.num_regions];
|
||||
ASSERT_TRUE(regions != nullptr);
|
||||
ASSERT_NE(regions, nullptr);
|
||||
|
||||
num_regions = odv.num_regions;
|
||||
err = amdsmi_get_gpu_od_volt_curve_regions(processor_handles_[i], &num_regions, regions);
|
||||
CHK_ERR_ASRT(err)
|
||||
ASSERT_TRUE(num_regions == odv.num_regions);
|
||||
err = amdsmi_get_gpu_od_volt_curve_regions(processor_handles_[i],
|
||||
&num_regions, regions);
|
||||
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "\t**amdsmi_get_gpu_od_volt_curve_regions("
|
||||
<< "processor_handles_[i], &num_regions, regions): "
|
||||
<< err << "\n"
|
||||
<< "\t**Number of regions: " << std::dec << num_regions
|
||||
<< "\n";
|
||||
}
|
||||
ASSERT_TRUE(err == AMDSMI_STATUS_SUCCESS
|
||||
|| err == AMDSMI_STATUS_NOT_SUPPORTED
|
||||
|| err == AMDSMI_STATUS_UNEXPECTED_DATA
|
||||
|| err == AMDSMI_STATUS_UNEXPECTED_SIZE
|
||||
|| err == AMDSMI_STATUS_INVAL);
|
||||
if (err != AMDSMI_STATUS_SUCCESS) {
|
||||
IF_VERB(STANDARD) {
|
||||
std::cout << "\t**amdsmi_get_gpu_od_volt_curve_regions: "
|
||||
"Not supported on this machine" << std::endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
|
||||
ASSERT_EQ(num_regions, odv.num_regions);
|
||||
|
||||
std::cout << "\t**Frequency-voltage curve regions:" << std::endl;
|
||||
print_amdsmi_od_volt_freq_regions(num_regions, regions);
|
||||
|
||||
Reference in New Issue
Block a user