diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | Makefile | 47 | ||||
| -rw-r--r-- | README.md | 83 | ||||
| -rw-r--r-- | libsmctrl.c | 212 | ||||
| -rw-r--r-- | libsmctrl_test_gpc_info.c | 4 | ||||
| -rw-r--r-- | libsmctrl_test_mask_shared.cu | 31 | ||||
| -rw-r--r-- | nvtaskset.c | 520 |
7 files changed, 659 insertions, 240 deletions
| @@ -8,6 +8,8 @@ libsmctrl_test_stream_mask | |||
| 8 | libsmctrl_test_stream_mask_override | 8 | libsmctrl_test_stream_mask_override |
| 9 | libsmctrl_test_next_mask | 9 | libsmctrl_test_next_mask |
| 10 | libsmctrl_test_next_mask_override | 10 | libsmctrl_test_next_mask_override |
| 11 | libcuda.so.1 | ||
| 12 | nvtaskset | ||
| 11 | *.pyc | 13 | *.pyc |
| 12 | *.o | 14 | *.o |
| 13 | .gdb_history | 15 | .gdb_history |
| @@ -3,9 +3,11 @@ CUDA ?= /usr/local/cuda | |||
| 3 | # Note that CXX and CC are predefined as g++ and cc (respectively) by Make | 3 | # Note that CXX and CC are predefined as g++ and cc (respectively) by Make |
| 4 | NVCC ?= $(CUDA)/bin/nvcc | 4 | NVCC ?= $(CUDA)/bin/nvcc |
| 5 | # Everything has to have -lcuda, as it's needed for libsmctrl | 5 | # Everything has to have -lcuda, as it's needed for libsmctrl |
| 6 | LDFLAGS := -lcuda -I$(CUDA)/include -L$(CUDA)/lib64 | 6 | LDFLAGS := -ldl -lcuda -I$(CUDA)/include -L$(CUDA)/lib64 |
| 7 | ARCH = $(shell $(CC) -dumpmachine) | ||
| 8 | CFLAGS := -Wall -Wno-parentheses | ||
| 7 | 9 | ||
| 8 | .PHONY: clean tests all | 10 | .PHONY: clean tests all install remove run_tests |
| 9 | 11 | ||
| 10 | # ----- Main Library ----- | 12 | # ----- Main Library ----- |
| 11 | libsmctrl.so: libsmctrl.c libsmctrl.h | 13 | libsmctrl.so: libsmctrl.c libsmctrl.h |
| @@ -14,9 +16,14 @@ libsmctrl.so: libsmctrl.c libsmctrl.h | |||
| 14 | # -fPIC is needed even if built as a static library, in case we are linked into | 16 | # -fPIC is needed even if built as a static library, in case we are linked into |
| 15 | # another shared library | 17 | # another shared library |
| 16 | libsmctrl.a: libsmctrl.c libsmctrl.h | 18 | libsmctrl.a: libsmctrl.c libsmctrl.h |
| 17 | $(CC) $< -c -o libsmctrl.o -fPIC $(CFLAGS) $(LDFLAGS) | 19 | $(CC) $< -c -o libsmctrl.o -fPIC -DLIBSMCTRL_STATIC $(CFLAGS) $(LDFLAGS) |
| 18 | ar rcs $@ libsmctrl.o | 20 | ar rcs $@ libsmctrl.o |
| 19 | 21 | ||
| 22 | # ----- CUDA Wrapper ----- | ||
| 23 | libcuda.so.1: libsmctrl.c libsmctrl.h | ||
| 24 | $(CC) $< -shared -o $@ -fPIC -DLIBSMCTRL_WRAPPER $(CFLAGS) $(LDFLAGS) | ||
| 25 | patchelf libcuda.so.1 --add-needed libcuda.so | ||
| 26 | |||
| 20 | # ----- Utilities ----- | 27 | # ----- Utilities ----- |
| 21 | # Use static linking with tests to avoid LD_LIBRARY_PATH issues | 28 | # Use static linking with tests to avoid LD_LIBRARY_PATH issues |
| 22 | nvtaskset: nvtaskset.c libsmctrl.so libsmctrl.a | 29 | nvtaskset: nvtaskset.c libsmctrl.so libsmctrl.a |
| @@ -29,7 +36,7 @@ libsmctrl_test_gpc_info: libsmctrl_test_gpc_info.c libsmctrl.a testbench.h | |||
| 29 | libsmctrl_test_mask_shared.o: libsmctrl_test_mask_shared.cu testbench.h | 36 | libsmctrl_test_mask_shared.o: libsmctrl_test_mask_shared.cu testbench.h |
| 30 | $(NVCC) -ccbin $(CXX) $< -c -g | 37 | $(NVCC) -ccbin $(CXX) $< -c -g |
| 31 | 38 | ||
| 32 | libsmctrl_test_supreme_mask: libsmctrl_test_supreme_mask.c libsmctrl.a libsmctrl_test_mask_shared.o | 39 | libsmctrl_test_supreme_mask: libsmctrl_test_supreme_mask.c libsmctrl.a libsmctrl_test_mask_shared.o libcuda.so.1 nvtaskset |
| 33 | $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS) | 40 | $(NVCC) -ccbin $(CXX) $@.c -o $@ libsmctrl_test_mask_shared.o -g -L. -l:libsmctrl.a $(LDFLAGS) |
| 34 | 41 | ||
| 35 | libsmctrl_test_global_mask: libsmctrl_test_global_mask.c libsmctrl.a libsmctrl_test_mask_shared.o | 42 | libsmctrl_test_global_mask: libsmctrl_test_global_mask.c libsmctrl.a libsmctrl_test_mask_shared.o |
| @@ -52,7 +59,7 @@ tests: libsmctrl_test_gpc_info libsmctrl_test_supreme_mask \ | |||
| 52 | libsmctrl_test_stream_mask_override libsmctrl_test_next_mask \ | 59 | libsmctrl_test_stream_mask_override libsmctrl_test_next_mask \ |
| 53 | libsmctrl_test_next_mask_override | 60 | libsmctrl_test_next_mask_override |
| 54 | 61 | ||
| 55 | all: libsmctrl.so nvtaskset tests | 62 | all: libsmctrl.so libcuda.so.1 nvtaskset tests |
| 56 | 63 | ||
| 57 | clean: | 64 | clean: |
| 58 | rm -f libsmctrl.so libsmctrl.o libsmctrl.a libsmctrl_test_gpc_info \ | 65 | rm -f libsmctrl.so libsmctrl.o libsmctrl.a libsmctrl_test_gpc_info \ |
| @@ -60,4 +67,32 @@ clean: | |||
| 60 | libsmctrl_test_global_mask \ | 67 | libsmctrl_test_global_mask \ |
| 61 | libsmctrl_test_stream_mask libsmctrl_test_stream_mask_override \ | 68 | libsmctrl_test_stream_mask libsmctrl_test_stream_mask_override \ |
| 62 | libsmctrl_test_next_mask libsmctrl_test_next_mask_override \ | 69 | libsmctrl_test_next_mask libsmctrl_test_next_mask_override \ |
| 63 | nvtaskset | 70 | nvtaskset libcuda.so.1 |
| 71 | |||
| 72 | install: libcuda.so.1 | ||
| 73 | @# Check that CUDA is installed first | ||
| 74 | test -f /lib/$(ARCH)/libcuda.so.*.* | ||
| 75 | @# Change libcuda.so link to bypass libcuda.so.1 | ||
| 76 | sudo ln -sf /lib/$(ARCH)/libcuda.so.*.* /lib/$(ARCH)/libcuda.so | ||
| 77 | @# Remove libcuda.so.1 symlink | ||
| 78 | sudo rm /lib/$(ARCH)/libcuda.so.1 | ||
| 79 | @# Install wrapper as libcuda.so.1 | ||
| 80 | sudo cp libcuda.so.1 /lib/$(ARCH)/libcuda.so.1 | ||
| 81 | |||
| 82 | remove: | ||
| 83 | @# Test that our library in installed first | ||
| 84 | test ! -L /lib/$(ARCH)/libcuda.so.1 | ||
| 85 | @# Overwrite install with original symlinks | ||
| 86 | sudo ln -sf libcuda.so.1 /lib/$(ARCH)/libcuda.so | ||
| 87 | sudo ln -sf /lib/$(ARCH)/libcuda.so.*.* /lib/$(ARCH)/libcuda.so.1 | ||
| 88 | |||
| 89 | run_tests: tests | ||
| 90 | ./libsmctrl_test_global_mask | ||
| 91 | ./libsmctrl_test_next_mask | ||
| 92 | ./libsmctrl_test_stream_mask | ||
| 93 | ./libsmctrl_test_next_mask_override | ||
| 94 | ./libsmctrl_test_stream_mask_override | ||
| 95 | @# Must set LD_LIBRARY_PATH in case make install has not been run | ||
| 96 | LD_LIBRARY_PATH=. ./libsmctrl_test_supreme_mask | ||
| 97 | ./libsmctrl_test_gpc_info | ||
| 98 | @ echo "All tests passed!" | ||
| @@ -13,16 +13,37 @@ Please cite this paper in any work which leverages our library. Here's the BibTe | |||
| 13 | year={2023}, | 13 | year={2023}, |
| 14 | month={May}, | 14 | month={May}, |
| 15 | pages={54--66}, | 15 | pages={54--66}, |
| 16 | doi={10.1109/RTAS58335.2023.00012}, | ||
| 16 | _series={RTAS} | 17 | _series={RTAS} |
| 17 | } | 18 | } |
| 18 | ``` | 19 | ``` |
| 19 | 20 | ||
| 20 | Please see [the paper](https://www.cs.unc.edu/~jbakita/rtas23.pdf) and `libsmctrl.h` for details and examples of how to use this library. | 21 | The ability for `libsmctrl` to work on unmodified tasks was developed as part of a follow-up paper: |
| 22 | |||
| 23 | _J. Bakita and J. H. Anderson, "Hardware Compute Partitioning on NVIDIA GPUs for Composable Systems", Proceedings of the 37th Euromicro Conference on Real-Time Systems, pp. 18:1-18:24, July 2025._ | ||
| 24 | |||
| 25 | Please cite this paper in any work which uses this for partitioning unmodified tasks. Here's the BibTeX entry: | ||
| 26 | ``` | ||
| 27 | @inproceedings{bakita2025hardware, | ||
| 28 | title={Hardware Compute Partitioning on {NVIDIA} {GPUs} for Composable Systems}, | ||
| 29 | author={Bakita, Joshua and Anderson, James H}, | ||
| 30 | booktitle={Proceedings of the 37th Euromicro Conference on Real-Time Systems}, | ||
| 31 | year={2025}, | ||
| 32 | month={July}, | ||
| 33 | pages={18:1--18:24}, | ||
| 34 | doi={10.1109/ECRTS.2025.18}, | ||
| 35 | _series={ECRTS} | ||
| 36 | } | ||
| 37 | ``` | ||
| 38 | |||
| 39 | Please see [the first paper](https://www.cs.unc.edu/~jbakita/rtas23.pdf), [the second paper](https://www.cs.unc.edu/~jbakita/ecrts25.pdf) and `libsmctrl.h` for details and examples of how to use this library. | ||
| 21 | We strongly encourage consulting those resources first; the below comments serve merely as an appendum. | 40 | We strongly encourage consulting those resources first; the below comments serve merely as an appendum. |
| 22 | 41 | ||
| 23 | ## Run-time Dependencies | 42 | ## Run-time Dependencies |
| 24 | `libcuda.so`, which is automatically installed by the NVIDIA GPU driver. | 43 | `libcuda.so`, which is automatically installed by the NVIDIA GPU driver. |
| 25 | 44 | ||
| 45 | (Technically `libdl` is also required, but this should never need to be manually installed. This is a dependency of CUDA, and is also part of the GNU C Standard Library starting with version 2.34.) | ||
| 46 | |||
| 26 | ## Building | 47 | ## Building |
| 27 | To build, ensure that you have `gcc` installed and access to the CUDA SDK including `nvcc`. Then run: | 48 | To build, ensure that you have `gcc` installed and access to the CUDA SDK including `nvcc`. Then run: |
| 28 | ``` | 49 | ``` |
| @@ -66,8 +87,52 @@ nvcc benchmark.cu -o benchmark -I/playpen/libsmctl -lsmctrl -lcuda -L/playpen/li | |||
| 66 | ``` | 87 | ``` |
| 67 | The resultant `benchmark` binary should be portable to any system with an equivalent or newer version of the NVIDIA GPU driver installed. | 88 | The resultant `benchmark` binary should be portable to any system with an equivalent or newer version of the NVIDIA GPU driver installed. |
| 68 | 89 | ||
| 90 | ## Use Without Application Modification | ||
| 91 | As an alternative to modifying your application, `libsmctrl` can be installed system-wide, and partitions for each application can be set via the `nvtaskset` tool. | ||
| 92 | The `nvtaskset` tool works very similarly to the Linux CPU-affinity-setting tool `taskset`. | ||
| 93 | |||
| 94 | To install `libsmctrl` system-wide, such that all CUDA-using applications automatically load it, ensure that `patchelf` is installed (`sudo apt install patchelf`), and run: | ||
| 95 | ``` | ||
| 96 | make libcuda.so.1 install | ||
| 97 | ``` | ||
| 98 | Or, if you do not want to modify any system-wide state, and only want `libsmctrl` loaded as part of anything run from this console: | ||
| 99 | ``` | ||
| 100 | make libcuda.so.1 | ||
| 101 | export LD_LIBRARY_PATH=$(pwd) | ||
| 102 | ``` | ||
| 103 | (This works because CUDA is always dynamically loaded from `libcuda.so.1`, and `lbsmctrl` creates a "fake" `libcuda.so.1` in this directory that wraps CUDA. | ||
| 104 | Setting `LD_LIBRARY_PATH` ensures that the wrapped version is the first one loaded. | ||
| 105 | The only difference with running `make install` is that it copies our "fake" `libcuda.so.1` to a location where the loader will automatically find it.) | ||
| 106 | |||
| 107 | And then to start an application within a specific TPC partition, e.g., the first 10 TPCs: | ||
| 108 | ``` | ||
| 109 | ./nvtaskset -t 0-9 my_program my_args | ||
| 110 | ``` | ||
| 111 | Note that this will automatically start NVIDIA MPS, which is a prerequisite to co-run tasks on NVIDIA GPUs without timeslicing. | ||
| 112 | |||
| 113 | And to change the TPCs available for a process ID 1234 to to the first 10 TPCs: | ||
| 114 | ``` | ||
| 115 | ./nvtaskset -tp 0-9 1234 | ||
| 116 | ``` | ||
| 117 | |||
| 118 | Or, to change a process of ID 1234 to only run on GPC 3: | ||
| 119 | ``` | ||
| 120 | ./nvtaskset -gp 3 1234 | ||
| 121 | ``` | ||
| 122 | |||
| 123 | To remove the system-wide installation of `libsmctrl`, run: | ||
| 124 | ``` | ||
| 125 | make remove | ||
| 126 | ``` | ||
| 127 | |||
| 69 | ## Run Tests | 128 | ## Run Tests |
| 70 | To test partitioning: | 129 | |
| 130 | To run them all: | ||
| 131 | ``` | ||
| 132 | make run_tests | ||
| 133 | ``` | ||
| 134 | |||
| 135 | If you prefer to run them individually, to test partitioning: | ||
| 71 | ``` | 136 | ``` |
| 72 | make tests | 137 | make tests |
| 73 | ./libsmctrl_test_global_mask | 138 | ./libsmctrl_test_global_mask |
| @@ -82,18 +147,26 @@ make tests | |||
| 82 | ./libsmctrl_test_next_mask_override | 147 | ./libsmctrl_test_next_mask_override |
| 83 | ``` | 148 | ``` |
| 84 | 149 | ||
| 85 | And if `nvdebug` has been installed: | 150 | To test that `nvtaskset` can dynamically change the mask of a running program: |
| 86 | ``` | 151 | ``` |
| 87 | make tests | 152 | make libsmctrl_test_supreme_mask |
| 153 | ./libsmctrl_test_supreme_mask | ||
| 154 | ``` | ||
| 155 | |||
| 15 | |||
