1.. _libc_gpu_testing: 2 3 4========================= 5Testing the GPU C library 6========================= 7 8.. note:: 9 Running GPU tests with high parallelism is likely to cause spurious failures, 10 out of resource errors, or indefinite hangs. limiting the number of threads 11 used while testing using ``LIBC_GPU_TEST_JOBS=<N>`` is highly recommended. 12 13.. contents:: Table of Contents 14 :depth: 4 15 :local: 16 17Testing infrastructure 18====================== 19 20The LLVM C library supports different kinds of :ref:`tests <build_and_test>` 21depending on the build configuration. The GPU target is considered a full build 22and therefore provides all of its own utilities to build and run the generated 23tests. Currently the GPU supports two kinds of tests. 24 25#. **Hermetic tests** - These are unit tests built with a test suite similar to 26 Google's ``gtest`` infrastructure. These use the same infrastructure as unit 27 tests except that the entire environment is self-hosted. This allows us to 28 run them on the GPU using our custom utilities. These are used to test the 29 majority of functional implementations. 30 31#. **Integration tests** - These are lightweight tests that simply call a 32 ``main`` function and checks if it returns non-zero. These are primarily used 33 to test interfaces that are sensitive to threading. 34 35The GPU uses the same testing infrastructure as the other supported ``libc`` 36targets. We do this by treating the GPU as a standard hosted environment capable 37of launching a ``main`` function. Effectively, this means building our own 38startup libraries and loader. 39 40Testing utilities 41================= 42 43We provide two utilities to execute arbitrary programs on the GPU. That is the 44``loader`` and the ``start`` object. 45 46Startup object 47-------------- 48 49This object mimics the standard object used by existing C library 50implementations. Its job is to perform the necessary setup prior to calling the 51``main`` function. In the GPU case, this means exporting GPU kernels that will 52perform the necessary operations. Here we use ``_begin`` and ``_end`` to handle 53calling global constructors and destructors while ``_start`` begins the standard 54execution. The following code block shows the implementation for AMDGPU 55architectures. 56 57.. code-block:: c++ 58 59 extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void 60 _begin(int argc, char **argv, char **env) { 61 LIBC_NAMESPACE::atexit(&LIBC_NAMESPACE::call_fini_array_callbacks); 62 LIBC_NAMESPACE::call_init_array_callbacks(argc, argv, env); 63 } 64 65 extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void 66 _start(int argc, char **argv, char **envp, int *ret) { 67 __atomic_fetch_or(ret, main(argc, argv, envp), __ATOMIC_RELAXED); 68 } 69 70 extern "C" [[gnu::visibility("protected"), clang::amdgpu_kernel]] void 71 _end(int retval) { 72 LIBC_NAMESPACE::exit(retval); 73 } 74 75Loader runtime 76-------------- 77 78The startup object provides a GPU executable with callable kernels for the 79respective runtime. We can then define a minimal runtime that will launch these 80kernels on the given device. Currently we provide the ``amdhsa-loader`` and 81``nvptx-loader`` targeting the AMD HSA runtime and CUDA driver runtime 82respectively. By default these will launch with a single thread on the GPU. 83 84.. code-block:: sh 85 86 $> clang++ crt1.o test.cpp --target=amdgcn-amd-amdhsa -mcpu=native -flto 87 $> amdhsa_loader --threads 1 --blocks 1 ./a.out 88 Test Passed! 89 90The loader utility will forward any arguments passed after the executable image 91to the program on the GPU as well as any set environment variables. The number 92of threads and blocks to be set can be controlled with ``--threads`` and 93``--blocks``. These also accept additional ``x``, ``y``, ``z`` variants for 94multidimensional grids. 95 96Running tests 97============= 98 99Tests will only be built and run if a GPU target architecture is set and the 100corresponding loader utility was built. These can be overridden with the 101``LIBC_GPU_TEST_ARCHITECTURE`` and ``LIBC_GPU_LOADER_EXECUTABLE`` :ref:`CMake 102options <gpu_cmake_options>`. Once built, they can be run like any other tests. 103The CMake target depends on how the library was built. 104 105#. **Cross build** - If the C library was built using ``LLVM_ENABLE_PROJECTS`` 106 or a runtimes cross build, then the standard targets will be present in the 107 base CMake build directory. 108 109 #. All tests - You can run all supported tests with the command: 110 111 .. code-block:: sh 112 113 $> ninja check-libc 114 115 #. Hermetic tests - You can run hermetic with tests the command: 116 117 .. code-block:: sh 118 119 $> ninja libc-hermetic-tests 120 121 #. Integration tests - You can run integration tests by the command: 122 123 .. code-block:: sh 124 125 $> ninja libc-integration-tests 126 127#. **Runtimes build** - If the library was built using ``LLVM_ENABLE_RUNTIMES`` 128 then the actual ``libc`` build will be in a separate directory. 129 130 #. All tests - You can run all supported tests with the command: 131 132 .. code-block:: sh 133 134 $> ninja check-libc-amdgcn-amd-amdhsa 135 $> ninja check-libc-nvptx64-nvidia-cuda 136 137 #. Specific tests - You can use the same targets as above by entering the 138 runtimes build directory. 139 140 .. code-block:: sh 141 142 $> ninja -C runtimes/runtimes-amdgcn-amd-amdhsa-bins check-libc 143 $> ninja -C runtimes/runtimes-nvptx64-nvidia-cuda-bins check-libc 144 $> cd runtimes/runtimes-amdgcn-amd-amdhsa-bins && ninja check-libc 145 $> cd runtimes/runtimes-nvptx64-nvidia-cuda-bins && ninja check-libc 146 147Tests can also be built and run manually using the respective loader utility. 148