aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile23
-rw-r--r--README.md1
-rw-r--r--libsmctrl.c163
-rw-r--r--libsmctrl.h4
-rw-r--r--libsmctrl_test_gpc_info.c72
-rw-r--r--libsmctrl_test_mask_shared.cu7
-rw-r--r--libsmctrl_test_mask_shared.h1
-rw-r--r--libsmctrl_test_supreme_mask.c10
-rw-r--r--nvtaskset.c210
10 files changed, 459 insertions, 33 deletions
diff --git a/.gitignore b/.gitignore
index 7c52826..5f0fdbe 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@ libsmctrl.a
2libsmctrl.o 2libsmctrl.o
3libsmctrl.so 3libsmctrl.so
4libsmctrl_test_gpc_info 4libsmctrl_test_gpc_info
5libsmctrl_test_supreme_mask
5libsmctrl_test_global_mask 6libsmctrl_test_global_mask
6libsmctrl_test_stream_mask 7libsmctrl_test_stream_mask
7libsmctrl_test_stream_mask_override 8libsmctrl_test_stream_mask_override
diff --git a/Makefile b/Makefile
index 5256634..62ec245 100644
--- a/Makefile
+++ b/Makefile
@@ -19,6 +19,9 @@ libsmctrl.a: libsmctrl.c libsmctrl.h
19 19
20# ----- Utilities ----- 20# ----- Utilities -----
21# Use static linking with tests to avoid LD_LIBRARY_PATH issues 21# Use static linking with tests to avoid LD_LIBRARY_PATH issues
22nvtaskset: nvtaskset.c libsmctrl.so libsmctrl.a
23 $(CC) $@.c -o $@ -L. -l:libsmctrl.a $(CFLAGS) $(LDFLAGS)
24
22libsmctrl_test_gpc_info: libsmctrl_test_gpc_info.c libsmctrl.a testbench.h 25libsmctrl_test_gpc_info: libsmctrl_test_gpc_info.c libsmctrl.a testbench.h
23 $(CC) $< -o $@ -g -L. -l:libsmctrl.a $(CFLAGS) $(LDFLAGS) 26 $(CC) $< -o $@ -g -L. -l:libsmctrl.a $(CFLAGS) $(LDFLAGS)
24 27
@@ -26,6 +29,9 @@ libsmctrl_test_gpc_info: libsmctrl_test_gpc_info.c libsmctrl.a testbench.h
26libsmctrl_test_mask_shared.o: libsmctrl_test_mask_shared.cu testbench.h 29libsmctrl_test_mask_shared.o: libsmctrl_test_mask_shared.cu testbench.h
27 $(NVCC) -ccbin $(CXX) $< -c -g 30 $(NVCC) -ccbin $(CXX) $< -c -g
28 31
32libsmctrl_test_supreme_mask: libsmctrl_test_supreme_mask.c libsmctrl.a libsmctrl_test_mask_shared.o
33 $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS)
34
29libsmctrl_test_global_mask: libsmctrl_test_global_mask.c libsmctrl.a libsmctrl_test_mask_shared.o 35libsmctrl_test_global_mask: libsmctrl_test_global_mask.c libsmctrl.a libsmctrl_test_mask_shared.o
30 $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS) 36 $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS)
31 37
@@ -41,12 +47,17 @@ libsmctrl_test_next_mask: libsmctrl_test_next_mask.c libsmctrl.a libsmctrl_test_
41libsmctrl_test_next_mask_override: libsmctrl_test_next_mask_override.c libsmctrl.a libsmctrl_test_mask_shared.o 47libsmctrl_test_next_mask_override: libsmctrl_test_next_mask_override.c libsmctrl.a libsmctrl_test_mask_shared.o
42 $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS) 48 $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS)
43 49
44tests: libsmctrl_test_gpc_info libsmctrl_test_global_mask libsmctrl_test_stream_mask libsmctrl_test_stream_mask_override libsmctrl_test_next_mask libsmctrl_test_next_mask_override 50tests: libsmctrl_test_gpc_info libsmctrl_test_supreme_mask \
51 libsmctrl_test_global_mask libsmctrl_test_stream_mask \
52 libsmctrl_test_stream_mask_override libsmctrl_test_next_mask \
53 libsmctrl_test_next_mask_override
45 54
46all: libsmctrl.so tests 55all: libsmctrl.so nvtaskset tests
47 56
48clean: 57clean:
49 rm -f libsmctrl.so libsmctrl.a libsmctrl_test_gpu_info \ 58 rm -f libsmctrl.so libsmctrl.o libsmctrl.a libsmctrl_test_gpc_info \
50 libsmctrl_test_mask_shared.o libmsctrl_test_global_mask \ 59 libsmctrl_test_mask_shared.o libsmctrl_test_supreme_mask \
51 libsmctrl_test_stream_mask libmsctrl_test_stream_mask_override \ 60 libsmctrl_test_global_mask \
52 libsmctrl_test_next_mask libmsctrl_test_next_mask_override 61 libsmctrl_test_stream_mask libsmctrl_test_stream_mask_override \
62 libsmctrl_test_next_mask libsmctrl_test_next_mask_override \
63 nvtaskset
diff --git a/README.md b/README.md
index f4d7cd1..f2be718 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,7 @@ make tests
103- Untested on non-Jetson `aarch64` platforms 103- Untested on non-Jetson `aarch64` platforms
104- Untested on CUDA 11.8, 12.0, and 12.1 on Jetson `aarch64` 104- Untested on CUDA 11.8, 12.0, and 12.1 on Jetson `aarch64`
105- Mask bit indexes do not directly correlate to software-visible TPC/SM IDs in V4 TMD/QMDs (Hopper+; compute capability 9.0). The mask bit indexes instead appear to correspond to on-chip-units, including disabled ones; i.e. the set of pre-SM-ID-remapping and pre-floorsweeping TPCs 105- Mask bit indexes do not directly correlate to software-visible TPC/SM IDs in V4 TMD/QMDs (Hopper+; compute capability 9.0). The mask bit indexes instead appear to correspond to on-chip-units, including disabled ones; i.e. the set of pre-SM-ID-remapping and pre-floorsweeping TPCs
106- Tests fail when NVIDIA MPS is enabled on Volta-generation and newer GPUs, as non-physical SM IDs are returned by `%%smid` register in this configuration (see US Patent 11,307,903 by NVIDIA)
106 107
107## Important Limitations 108## Important Limitations
108 109
diff --git a/libsmctrl.c b/libsmctrl.c
index 5ee94fb..6aa471b 100644
--- a/libsmctrl.c
+++ b/libsmctrl.c
@@ -31,6 +31,8 @@
31#include <stdbool.h> 31#include <stdbool.h>
32#include <stdint.h> 32#include <stdint.h>
33#include <stdio.h> 33#include <stdio.h>
34#include <sys/ipc.h>
35#include <sys/shm.h>
34#include <unistd.h> 36#include <unistd.h>
35 37
36#include "libsmctrl.h" 38#include "libsmctrl.h"
@@ -52,6 +54,8 @@ static const CUuuid callback_funcs_id = {0x2c, (char)0x8e, 0x0a, (char)0xd8, 0x0
52// structures, allowing us to override it with the next mask. 54// structures, allowing us to override it with the next mask.
53#define QMD_DOMAIN 0xb 55#define QMD_DOMAIN 0xb
54#define QMD_PRE_UPLOAD 0x1 56#define QMD_PRE_UPLOAD 0x1
57// Supreme mask (cannot be overridden)
58static uint64_t *g_supreme_sm_mask = NULL;
55// Global mask (applies across all threads) 59// Global mask (applies across all threads)
56static uint64_t g_sm_mask = 0; 60static uint64_t g_sm_mask = 0;
57// Next mask (applies per-thread) 61// Next mask (applies per-thread)
@@ -110,6 +114,13 @@ static void control_callback_v2(void *ukwn, int domain, int cbid, const void *in
110 *upper_ptr = (uint32_t)(g_sm_mask >> 32); 114 *upper_ptr = (uint32_t)(g_sm_mask >> 32);
111 } 115 }
112 116
117 // No one may override the supreme SM mask; any SMs disabled in it (set
118 // bits) must always remain disabled.
119 if (g_supreme_sm_mask) {
120 *lower_ptr |= (uint32_t)*g_supreme_sm_mask;
121 *upper_ptr |= (uint32_t)(*g_supreme_sm_mask >> 32);
122 }
123
113 //fprintf(stderr, "Final SM Mask (lower): %x\n", *lower_ptr); 124 //fprintf(stderr, "Final SM Mask (lower): %x\n", *lower_ptr);
114 //fprintf(stderr, "Final SM Mask (upper): %x\n", *upper_ptr); 125 //fprintf(stderr, "Final SM Mask (upper): %x\n", *upper_ptr);
115} 126}
@@ -423,13 +434,30 @@ static int read_int_procfile(char* filename, uint64_t* out) {
423 return 0; 434 return 0;
424} 435}
425 436
426// We support up to 64 TPCs, up to 12 GPCs per GPU, and up to 16 GPUs. 437// We support up to 128 TPCs, up to 12 GPCs per GPU, and up to 16 GPUs.
427// TODO: Handle GPUs with greater than 64 TPCs (e.g. some H100 variants) 438#define MAX_GPCS 12
428static uint64_t tpc_mask_per_gpc_per_dev[16][12]; 439static uint64_t tpc_mask_per_gpc_per_dev[16][MAX_GPCS];
440static uint128_t tpc_mask_per_gpc_per_dev_ext[16][MAX_GPCS];
429// Output mask is vtpc-indexed (virtual TPC) 441// Output mask is vtpc-indexed (virtual TPC)
442// Note that this function has to undo _both_ floorsweeping and ID remapping
430int libsmctrl_get_gpc_info(uint32_t* num_enabled_gpcs, uint64_t** tpcs_for_gpc, int dev) { 443int libsmctrl_get_gpc_info(uint32_t* num_enabled_gpcs, uint64_t** tpcs_for_gpc, int dev) {
431 uint32_t i, j, vtpc_idx = 0; 444 int err, i;
432 uint64_t gpc_mask, num_tpc_per_gpc, max_gpcs, gpc_tpc_mask; 445 uint128_t *tpcs_for_gpc_ext;
446 if ((err = libsmctrl_get_gpc_info_ext(num_enabled_gpcs, &tpcs_for_gpc_ext, dev)))
447 return err;
448 for (i = 0; i < *num_enabled_gpcs; i++) {
449 if ((tpcs_for_gpc_ext[i] & -1ull) != tpcs_for_gpc_ext[i])
450 return ERANGE;
451 tpc_mask_per_gpc_per_dev[dev][i] = (uint64_t)tpcs_for_gpc_ext[i];
452 }
453 *tpcs_for_gpc = tpc_mask_per_gpc_per_dev[dev];
454 return 0;
455}
456
457int libsmctrl_get_gpc_info_ext(uint32_t* num_enabled_gpcs, uint128_t** tpcs_for_gpc, int dev) {
458 uint32_t i, j, tpc_id, gpc_id, num_enabled_tpcs, num_configured_tpcs;
459 uint64_t gpc_mask, num_tpc_per_gpc, max_gpcs, gpc_tpc_mask, gpc_tpc_config, total_read = 0;
460 uint128_t tpc_bit;
433 int err; 461 int err;
434 char filename[100]; 462 char filename[100];
435 *num_enabled_gpcs = 0; 463 *num_enabled_gpcs = 0;
@@ -449,43 +477,79 @@ int libsmctrl_get_gpc_info(uint32_t* num_enabled_gpcs, uint64_t** tpcs_for_gpc,
449 snprintf(filename, 100, "/proc/gpu%d/gpc_mask", dev); 477 snprintf(filename, 100, "/proc/gpu%d/gpc_mask", dev);
450 if (err = read_int_procfile(filename, &gpc_mask)) 478 if (err = read_int_procfile(filename, &gpc_mask))
451 return err; 479 return err;
480 // Determine the number of enabled TPCs
452 snprintf(filename, 100, "/proc/gpu%d/num_tpc_per_gpc", dev); 481 snprintf(filename, 100, "/proc/gpu%d/num_tpc_per_gpc", dev);
453 if (err = read_int_procfile(filename, &num_tpc_per_gpc)) 482 if (err = read_int_procfile(filename, &num_tpc_per_gpc))
454 return err; 483 return err;
455 // For each enabled GPC 484 // For each enabled GPC
485 num_enabled_tpcs = 0;
456 for (i = 0; i < max_gpcs; i++) { 486 for (i = 0; i < max_gpcs; i++) {
457 // Skip this GPC if disabled 487 // Skip this GPC if disabled
458 if ((1 << i) & gpc_mask) 488 if ((1 << i) & gpc_mask)
459 continue; 489 continue;
460 (*num_enabled_gpcs)++; 490 (*num_enabled_gpcs)++;
461 // Get the bitstring of TPCs disabled for this GPC 491 // Get the bitstring of TPCs disabled for this physical GPC
462 // Set bit = disabled TPC 492 // Set bit = disabled TPC
463 snprintf(filename, 100, "/proc/gpu%d/gpc%d_tpc_mask", dev, i); 493 snprintf(filename, 100, "/proc/gpu%d/gpc%d_tpc_mask", dev, i);
464 if (err = read_int_procfile(filename, &gpc_tpc_mask)) 494 if (err = read_int_procfile(filename, &gpc_tpc_mask))
465 return err; 495 return err;
466 uint64_t* tpc_mask = &tpc_mask_per_gpc_per_dev[dev][*num_enabled_gpcs - 1]; 496 // Bits greater than the max number of TPCs should be ignored, so only
467 *tpc_mask = 0; 497 // keep the `num_tpc_per_gpc`-count number of lower bits.
468 for (j = 0; j < num_tpc_per_gpc; j++) { 498 gpc_tpc_mask &= -1u >> (64 - num_tpc_per_gpc);
469 // Skip disabled TPCs 499 // Number of enabled TPCs = max - number disabled
470 if ((1 << j) & gpc_tpc_mask) 500 num_enabled_tpcs += num_tpc_per_gpc - __builtin_popcountl(gpc_tpc_mask);
471 continue; 501 }
472 *tpc_mask |= (1ull << vtpc_idx); 502 // Clear any previous mask
473 vtpc_idx++; 503 for (i = 0; i < MAX_GPCS; i++)
504 tpc_mask_per_gpc_per_dev_ext[dev][i] = 0;
505 // For each enabled TPC
506 for (tpc_id = 0; tpc_id < num_enabled_tpcs;) {
507 // Pull mapping for the next set of 4 TPCs
508 snprintf(filename, 100, "/proc/gpu%d/CWD_GPC_TPC_ID%d", dev, tpc_id / 4);
509 if (err = read_int_procfile(filename, &gpc_tpc_config))
510 return err;
511 total_read += gpc_tpc_config;
512 for (j = 0; j < 4 && tpc_id < num_enabled_tpcs; j++, tpc_id++) {
513 // Set the bit for the current TPC
514 tpc_bit = 1;
515 tpc_bit <<= tpc_id;
516 // Determine which GPC the current TPC is associated with
517 // (upper 4 bits of each byte)
518 gpc_i