From 9ed721de0e9ce564b7c852e38359398b019a5c2f Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Thu, 16 Mar 2023 02:18:35 -0400 Subject: Introduce pysmctrl: A python interface to libsmctrl Initially supports the GPU information functions via: - pysmctrl.get_gpc_info(dev_id) - pysmctrl.get_tpc_info(dev_id) - pysmctrl.get_tpc_info_cuda(cuda_dev_id) All functions are extensively documented. See pysmctrl/__init__.py for details. Device partitioning functions have yet to be mapped into Python, as these will require more testing. As part of this: - libsmctrl_get_*_info() functions have been modified to consistently return positive error codes. - libsmctrl_get_tpc_info() now uses nvdebug-style device numbering and uses libsmctrl_get_gpc_info() under the covers. This should be more reliable. - libsmctrl_get_tpc_info_cuda() has been introduced as an improved version of the old libsmctrl_get_tpc_info() function. This continues to use CUDA-style device numbering, but is now resiliant to CUDA failures. - Various minor style improvements in libsmctrl.c --- pysmctrl/__init__.py | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 pysmctrl/__init__.py (limited to 'pysmctrl') diff --git a/pysmctrl/__init__.py b/pysmctrl/__init__.py new file mode 100644 index 0000000..5dc6175 --- /dev/null +++ b/pysmctrl/__init__.py @@ -0,0 +1,82 @@ +import ctypes, ctypes.util +import os + +# If this is failing, make sure that the directory containing libsmctrl.so is +# in your LD_LIBRARY_PATH environment variable. You likely need something like: +# LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/playpen/jbakita/gpu_subdiv/libsmctrl/ +libsmctrl_path = ctypes.util.find_library("libsmctrl") +if not libsmctrl_path: + libsmctrl_path = __path__[0] + "/../libsmctrl.so" +libsmctrl = ctypes.CDLL(libsmctrl_path) + +def get_gpc_info(device_num): + """ + Obtain list of thread processing clusters (TPCs) enabled for each general + processing cluster (GPC) in the specified GPU. + + Parameters + ---------- + device_num : int + Which device to obtain information for (starts as 0, order is defined + by nvdebug module). May not match CUDA device numbering. + + Returns + ------- + list of int64 + A list as long as the number of GPCs enabled, where each list entry is + a bitmask. A bit set at index `i` indicates that TPC `i` is part of the + GPC at that list index. Obtained via GPU register reads in `nvdebug`. + """ + num_gpcs = ctypes.c_uint() + tpc_masks = ctypes.pointer(ctypes.c_ulonglong()) + res = libsmctrl.libsmctrl_get_gpc_info(ctypes.byref(num_gpcs), ctypes.byref(tpc_masks), device_num) + if res != 0: + print("pysmctrl: Unable to call libsmctrl_get_gpc_info(). Raising error %d..."%res) + raise OSError(res, os.strerror(res)) + return [tpc_masks[i] for i in range(num_gpcs.value)] + +def get_tpc_info(device_num): + """ + Obtain a count of the total number of thread processing clusters (TPCs) + enabled on the specified GPU. + + Parameters + ---------- + device_num : int + Which device to obtain TPC count for (starts as 0, order is defined by + `nvdebug` module). May not match CUDA device numbering. + + Returns + ------- + int + Count of enabled TPCs. Obtained via GPU register reads in `nvdebug`. + """ + num_tpcs = ctypes.c_uint() + res = libsmctrl.libsmctrl_get_tpc_info(ctypes.byref(num_tpcs), device_num) + if res != 0: + print("pysmctrl: Unable to call libsmctrl_get_tpc_info(). Raising error %d..."%res) + raise OSError(res, os.strerror(res)) + return num_tpcs.value + +def get_tpc_info_cuda(device_num): + """ + Obtain a count of the total number of thread processing clusters (TPCs) + enabled on the specified GPU. + + Parameters + ---------- + device_num : int + Which device to obtain TPC count for, as a CUDA device ID. + + Returns + ------- + int + Count of enabled TPCs. Obtained via calculations on data from CUDA. + """ + num_tpcs = ctypes.c_uint() + res = libsmctrl.libsmctrl_get_tpc_info_cuda(ctypes.byref(num_tpcs), device_num) + if res != 0: + print("pysmctrl: Unable to call libsmctrl_get_tpc_info_cuda(). Raising error %d..."%res) + raise OSError(res, os.strerror(res)) + return num_tpcs.value + -- cgit v1.2.2