From ff710b83a2e6040e0e0e419f28f80c2153796e59 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 27 Feb 2023 09:39:40 -0500 Subject: [PATCH 01/14] Add rapids_test allowing projects to run gpu tests in parallel Introduces rapids_test functionality to allow tests executed via ctest -j to properly resource share GPUs. This is done by having tests state how many GPUs allocations they require, and uses CTest internal job scheduler to properly load balance. --- README.md | 10 ++ cmake-format-rapids-cmake.json | 43 ++++- dependencies.yaml | 5 + docs/api.rst | 15 ++ docs/command/rapids_test_add.rst | 1 + .../rapids_test_generate_resource_spec.rst | 1 + docs/command/rapids_test_gpu_requirements.rst | 1 + docs/command/rapids_test_init.rst | 1 + .../rapids_test_install_relocatable.rst | 1 + .../rapids_cmake_ctest_allocation.cpp | 96 +++++++++++ .../rapids_cmake_ctest_allocation.hpp | 89 +++++++++++ docs/hardware_resources_and_testing.rst | 121 ++++++++++++++ docs/index.rst | 1 + rapids-cmake/rapids-test.cmake | 21 +++ rapids-cmake/test/add.cmake | 149 ++++++++++++++++++ .../test/detail/generate_resource_spec.cpp | 87 ++++++++++ rapids-cmake/test/detail/record_install.cmake | 43 +++++ .../test/detail/record_test_command.cmake | 40 +++++ .../test/detail/record_test_component.cmake | 42 +++++ rapids-cmake/test/detail/run_gpu_test.cmake | 33 ++++ .../test/generate_resource_spec.cmake | 94 +++++++++++ rapids-cmake/test/gpu_requirements.cmake | 92 +++++++++++ rapids-cmake/test/init.cmake | 64 ++++++++ rapids-cmake/test/install_relocatable.cmake | 112 +++++++++++++ testing/CMakeLists.txt | 5 + testing/test/CMakeLists.txt | 58 +++++++ .../test/add-allocation-simple/CMakeLists.txt | 31 ++++ testing/test/add-allocation-simple/main.cu | 30 ++++ .../add-impossible-allocation/CMakeLists.txt | 26 +++ .../test/add-impossible-allocation/main.cu | 20 +++ .../CMakeLists.txt | 31 ++++ .../add-multi-allocations-same-gpu/main.cu | 29 ++++ .../add-multi-jobs-single-gpu/CMakeLists.txt | 35 ++++ .../test/add-multi-jobs-single-gpu/main.cu | 53 +++++++ .../add-single-job-multi-gpu/CMakeLists.txt | 26 +++ testing/test/add-single-job-multi-gpu/main.cu | 30 ++++ testing/test/add-with-install-component.cmake | 45 ++++++ testing/test/add-with-no-gpus.cmake | 32 ++++ testing/test/detail/file_locker.hpp | 81 ++++++++++ .../test/generate_resource_spec-no-gpus.cmake | 37 +++++ .../test/generate_resource_spec-simple.cmake | 29 ++++ testing/test/gpu_requirements-char-gpu.cmake | 19 +++ .../test/gpu_requirements-char-percent.cmake | 19 +++ .../test/gpu_requirements-max-percent.cmake | 20 +++ .../test/gpu_requirements-min-percent.cmake | 20 +++ testing/test/gpu_requirements-multi.cmake | 25 +++ .../test/gpu_requirements-negative-gpu.cmake | 20 +++ .../gpu_requirements-negative-percent.cmake | 20 +++ testing/test/gpu_requirements-no-gpus.cmake | 20 +++ .../test/gpu_requirements-no-percent.cmake | 25 +++ .../gpu_requirements-over-max-percent.cmake | 20 +++ testing/test/gpu_requirements-single.cmake | 25 +++ testing/test/gpu_requirements-zero-gpu.cmake | 19 +++ .../test/gpu_requirements-zero-percent.cmake | 20 +++ testing/test/init-existing-specfile.cmake | 25 +++ testing/test/init-simple.cmake | 28 ++++ testing/test/install_relocatable-labels.cmake | 36 +++++ testing/test/install_relocatable-simple.cmake | 45 ++++++ .../install_relocatable-wrong-component.cmake | 26 +++ .../CMakeLists.txt | 32 ++++ .../main.cpp | 34 ++++ .../CMakeLists.txt | 39 +++++ .../no_add-with-no-resource-spec/main.cpp | 30 ++++ testing/test/rapids-test.cmake | 16 ++ testing/utils/cmake_ctest_test.cmake | 22 +++ testing/utils/cmake_test.cmake | 33 +++- testing/utils/determine_gpu_count.cmake | 25 +++ 67 files changed, 2419 insertions(+), 4 deletions(-) create mode 100644 docs/command/rapids_test_add.rst create mode 100644 docs/command/rapids_test_generate_resource_spec.rst create mode 100644 docs/command/rapids_test_gpu_requirements.rst create mode 100644 docs/command/rapids_test_init.rst create mode 100644 docs/command/rapids_test_install_relocatable.rst create mode 100644 docs/cpp_code_snippets/rapids_cmake_ctest_allocation.cpp create mode 100644 docs/cpp_code_snippets/rapids_cmake_ctest_allocation.hpp create mode 100644 docs/hardware_resources_and_testing.rst create mode 100644 rapids-cmake/rapids-test.cmake create mode 100644 rapids-cmake/test/add.cmake create mode 100644 rapids-cmake/test/detail/generate_resource_spec.cpp create mode 100644 rapids-cmake/test/detail/record_install.cmake create mode 100644 rapids-cmake/test/detail/record_test_command.cmake create mode 100644 rapids-cmake/test/detail/record_test_component.cmake create mode 100644 rapids-cmake/test/detail/run_gpu_test.cmake create mode 100644 rapids-cmake/test/generate_resource_spec.cmake create mode 100644 rapids-cmake/test/gpu_requirements.cmake create mode 100644 rapids-cmake/test/init.cmake create mode 100644 rapids-cmake/test/install_relocatable.cmake create mode 100644 testing/test/CMakeLists.txt create mode 100644 testing/test/add-allocation-simple/CMakeLists.txt create mode 100644 testing/test/add-allocation-simple/main.cu create mode 100644 testing/test/add-impossible-allocation/CMakeLists.txt create mode 100644 testing/test/add-impossible-allocation/main.cu create mode 100644 testing/test/add-multi-allocations-same-gpu/CMakeLists.txt create mode 100644 testing/test/add-multi-allocations-same-gpu/main.cu create mode 100644 testing/test/add-multi-jobs-single-gpu/CMakeLists.txt create mode 100644 testing/test/add-multi-jobs-single-gpu/main.cu create mode 100644 testing/test/add-single-job-multi-gpu/CMakeLists.txt create mode 100644 testing/test/add-single-job-multi-gpu/main.cu create mode 100644 testing/test/add-with-install-component.cmake create mode 100644 testing/test/add-with-no-gpus.cmake create mode 100644 testing/test/detail/file_locker.hpp create mode 100644 testing/test/generate_resource_spec-no-gpus.cmake create mode 100644 testing/test/generate_resource_spec-simple.cmake create mode 100644 testing/test/gpu_requirements-char-gpu.cmake create mode 100644 testing/test/gpu_requirements-char-percent.cmake create mode 100644 testing/test/gpu_requirements-max-percent.cmake create mode 100644 testing/test/gpu_requirements-min-percent.cmake create mode 100644 testing/test/gpu_requirements-multi.cmake create mode 100644 testing/test/gpu_requirements-negative-gpu.cmake create mode 100644 testing/test/gpu_requirements-negative-percent.cmake create mode 100644 testing/test/gpu_requirements-no-gpus.cmake create mode 100644 testing/test/gpu_requirements-no-percent.cmake create mode 100644 testing/test/gpu_requirements-over-max-percent.cmake create mode 100644 testing/test/gpu_requirements-single.cmake create mode 100644 testing/test/gpu_requirements-zero-gpu.cmake create mode 100644 testing/test/gpu_requirements-zero-percent.cmake create mode 100644 testing/test/init-existing-specfile.cmake create mode 100644 testing/test/init-simple.cmake create mode 100644 testing/test/install_relocatable-labels.cmake create mode 100644 testing/test/install_relocatable-simple.cmake create mode 100644 testing/test/install_relocatable-wrong-component.cmake create mode 100644 testing/test/no_add-with-cpp-handler-from-docs/CMakeLists.txt create mode 100644 testing/test/no_add-with-cpp-handler-from-docs/main.cpp create mode 100644 testing/test/no_add-with-no-resource-spec/CMakeLists.txt create mode 100644 testing/test/no_add-with-no-resource-spec/main.cpp create mode 100644 testing/test/rapids-test.cmake create mode 100644 testing/utils/cmake_ctest_test.cmake create mode 100644 testing/utils/determine_gpu_count.cmake diff --git a/README.md b/README.md index cf41bfad..c7ab70fd 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,16 @@ The most commonly used function are: - `rapids_find_package( BUILD_EXPORT_SET INSTALL_EXPORT_SET )` Combines `find_package` and support to track dependencies for easy package exporting - `rapids_generate_module( HEADER_NAMES LIBRARY_NAMES )` Generate a FindModule for the given package. Allows association to export sets so the generated FindModule can be shipped with the project +### test + +The `rapids_test` functions simplify CTest resource allocation, allowing for +tests to run in parallel without overallocating GPU resources. + +The most commonly used functions are: +- `rapids_test_add(NAME GPUS )` State how many GPU resources a single + test requires + + ## Overriding RAPIDS.cmake At times projects or developers will need to verify ``rapids-cmake`` branches. To do this you can set variables that control which repository ``RAPIDS.cmake`` downloads, which should be done like this: diff --git a/cmake-format-rapids-cmake.json b/cmake-format-rapids-cmake.json index 0f16604b..9d784111 100644 --- a/cmake-format-rapids-cmake.json +++ b/cmake-format-rapids-cmake.json @@ -310,8 +310,49 @@ "TARGET": "1", "ROOT_DIRECTORY": "1" } + }, + "rapids_test_init": { + "pargs": { + "nargs": "0" + } + }, + "rapids_test_add": { + "pargs": { + "nargs": "0" + }, + "kwargs": { + "NAME": "1", + "COMMAND": "*", + "INSTALL_COMPONENT_SET": "1", + "GPUS": "1", + "PERCENT": "1", + "WORKING_DIRECTORY": "1" + } + }, + "rapids_test_gpu_requirements": { + "pargs": { + "nargs": "1" + }, + "kwargs": { + "GPUS": "1", + "PERCENT": "1" + } + }, + "rapids_test_generate_resource_spec": { + "pargs": { + "nargs": "2" + } + }, + "rapids_test_install_relocatable": { + "pargs": { + "nargs": "0", + "flags": ["EXCLUDE_FROM_ALL"] + }, + "kwargs": { + "INSTALL_COMPONENT_SET": "1", + "DESTINATION": "1" + } } - } } } diff --git a/dependencies.yaml b/dependencies.yaml index 1e72f2a3..c6139e25 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -41,23 +41,28 @@ dependencies: packages: - cudatoolkit=11.2 - gcc<11.0.0 + - sysroot_linux-64==2.17 - matrix: cuda: "11.4" packages: - cudatoolkit=11.4 - gcc<11.0.0 + - sysroot_linux-64==2.17 - matrix: cuda: "11.5" packages: - cudatoolkit=11.5 + - sysroot_linux-64==2.17 - matrix: cuda: "11.6" packages: - cudatoolkit=11.6 + - sysroot_linux-64==2.17 - matrix: cuda: "11.8" packages: - cudatoolkit=11.8 + - sysroot_linux-64==2.17 docs: common: - output_types: [conda] diff --git a/docs/api.rst b/docs/api.rst index 1543157c..fa4a6389 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -133,3 +133,18 @@ correct export generation. These should only be used when :cmake:command:`rapids rapids_export_find_package_file [Advanced] rapids_export_find_package_root [Advanced] rapids_export_package [Advanced] + +Testing +******* + +The `rapids_test` functions simplify CTest resource allocation, allowing for tests to run in parallel without over-allocating GPU resources. +More information on resource allocation can be found in the rapids-cmake :ref:`Hardware Resources and Testing documentation `. + +.. toctree:: + :titlesonly: + + /command/rapids_test_init + /command/rapids_test_add + /command/rapids_test_generate_resource_spec + /command/rapids_test_gpu_requirements + /command/rapids_test_install_relocatable diff --git a/docs/command/rapids_test_add.rst b/docs/command/rapids_test_add.rst new file mode 100644 index 00000000..36470911 --- /dev/null +++ b/docs/command/rapids_test_add.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../rapids-cmake/test/add.cmake diff --git a/docs/command/rapids_test_generate_resource_spec.rst b/docs/command/rapids_test_generate_resource_spec.rst new file mode 100644 index 00000000..3102af2f --- /dev/null +++ b/docs/command/rapids_test_generate_resource_spec.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../rapids-cmake/test/generate_resource_spec.cmake diff --git a/docs/command/rapids_test_gpu_requirements.rst b/docs/command/rapids_test_gpu_requirements.rst new file mode 100644 index 00000000..4e596056 --- /dev/null +++ b/docs/command/rapids_test_gpu_requirements.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../rapids-cmake/test/gpu_requirements.cmake diff --git a/docs/command/rapids_test_init.rst b/docs/command/rapids_test_init.rst new file mode 100644 index 00000000..7e5994a1 --- /dev/null +++ b/docs/command/rapids_test_init.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../rapids-cmake/test/init.cmake diff --git a/docs/command/rapids_test_install_relocatable.rst b/docs/command/rapids_test_install_relocatable.rst new file mode 100644 index 00000000..5ee62de2 --- /dev/null +++ b/docs/command/rapids_test_install_relocatable.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../rapids-cmake/test/install_relocatable.cmake diff --git a/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.cpp b/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.cpp new file mode 100644 index 00000000..1a35a9d8 --- /dev/null +++ b/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +namespace rapids_cmake { + +namespace { +GPUAllocation noGPUAllocation() { return GPUAllocation{-1, -1}; } + +GPUAllocation parseCTestAllocation(std::string_view env_variable) +{ + std::string gpu_resources{std::getenv(env_variable.begin())}; + // need to handle parseCTestAllocation variable being empty + + // need to handle parseCTestAllocation variable not having some + // of the requested components + + // The string looks like "id:,slots:" + auto id_start = gpu_resources.find("id:") + 3; + auto id_end = gpu_resources.find(","); + auto slot_start = gpu_resources.find("slots:") + 6; + + auto id = gpu_resources.substr(id_start, id_end - id_start); + auto slots = gpu_resources.substr(slot_start); + + return GPUAllocation{std::stoi(id), std::stoi(slots)}; +} + +std::vector determineGPUAllocations() +{ + std::vector allocations; + const auto* resource_count = std::getenv("CTEST_RESOURCE_GROUP_COUNT"); + if (!resource_count) { + allocations.emplace_back(); + return allocations; + } + + const auto resource_max = std::stoi(resource_count); + for (int index = 0; index < resource_max; ++index) { + std::string group_env = "CTEST_RESOURCE_GROUP_" + std::to_string(index); + std::string resource_group{std::getenv(group_env.c_str())}; + std::transform(resource_group.begin(), resource_group.end(), resource_group.begin(), ::toupper); + + if (resource_group == "GPUS") { + auto resource_env = group_env + "_" + resource_group; + auto&& allocation = parseCTestAllocation(resource_env); + allocations.emplace_back(allocation); + } + } + + return allocations; +} +} // namespace + +bool using_resources() +{ + const auto* resource_count = std::getenv("CTEST_RESOURCE_GROUP_COUNT"); + return resource_count != nullptr; +} + +std::vector full_allocation() { return determineGPUAllocations(); } + +cudaError_t bind_to_gpu(GPUAllocation const& alloc) { return cudaSetDevice(alloc.device_id); } + +bool bind_to_first_gpu() +{ + if (using_resources()) { + std::vector allocs = determineGPUAllocations(); + return (bind_to_gpu(allocs[0]) == cudaSuccess); + } + return false; +} + +} // namespace rapids_cmake diff --git a/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.hpp b/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.hpp new file mode 100644 index 00000000..7acc84ea --- /dev/null +++ b/docs/cpp_code_snippets/rapids_cmake_ctest_allocation.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace rapids_cmake { + +/* + * Represents a GPU Allocation provided by a CTest resource specification. + * + * The `device_id` maps to the CUDA gpu id required by `cudaSetDevice`. + * The slots represent the percentage of the GPU that this test will use. + * Primarily used by CTest to ensure proper load balancing of tests. + */ +struct GPUAllocation { + int device_id; + int slots; +}; + +/* + * Returns true when a CTest resource specification has been specified. + * + * Since the vast majority of tests should execute without a CTest resource + * spec (e.g. when executed manually by a developer), callers of `rapids_cmake` + * should first ensure that a CTestresource spec file has been provided before + * trying to query/bind to the allocation. + * + * ```cxx + * if (rapids_cmake::using_resouces()) { + * rapids_cmake::bind_to_first_gpu(); + * } + * ``` + */ +bool using_resources(); + +/* + * Returns all GPUAllocations allocated for a test + * + * To support multi-GPU tests the CTest resource specification allows a + * test to request multiple GPUs. As CUDA only allows binding to a + * single GPU at any time, this API allows tests to know what CUDA + * devices they should bind to. + * + * Note: The `device_id` of each allocation might not be unique. + * If a test says it needs 50% of two GPUs, it could be allocated + * the same physical GPU. If a test needs distinct / unique devices + * it must request 51%+ of a device. + * + * Note: rapids_cmake does no caching, so this query should be cached + * instead of called multiple times. + */ +std::vector full_allocation(); + +/* + * Have CUDA bind to a given GPUAllocation + * + * Have CUDA bind to the `device_id` specified in the CTest + * GPU allocation + * + * Note: Return value is the cudaError_t of `cudaSetDevice` + */ +cudaError_t bind_to_gpu(GPUAllocation const& alloc); + +/* + * Convenience method to bind to the first GPU that CTest has allocated + * Provided as most RAPIDS tests only require a single GPU + * + * Will return `false` if no GPUs have been allocated, or if setting + * the CUDA device failed for any reason. + */ +bool bind_to_first_gpu(); + +} // namespace rapids_cmake diff --git a/docs/hardware_resources_and_testing.rst b/docs/hardware_resources_and_testing.rst new file mode 100644 index 00000000..3787e546 --- /dev/null +++ b/docs/hardware_resources_and_testing.rst @@ -0,0 +1,121 @@ + +.. _rapids_resource_allocation: + +Hardware Resources and Testing +############################## + + +Resource Allocation +******************* + +CTest resource allocation frameworks allow tests to specify which hardware resources that they need, and for projects to specify the specific local/machine resources available. +Combined together this ensures that tests are told which specific resources they should use, and ensures over-subscription won't occur no matter the requested testing parallel level. + +To get CTest resource allocation used by tests the following components are needed. + + - A JSON per-machine resource specification file + - The :cmake:variable:`CTEST_RESOURCE_SPEC_FILE` points to the JSON file + - Each :cmake:command:`add_test` records what resources it requires via test properties + - Each test reads the relevant environment variables to determine + what specific resources it should use + + +These are steep requirements that require large amounts of infrastructure setup for each project. +In addition the CTest resource allocation specification is very relaxed, allowing it to represent arbitrary requirements such as CPUs, GPUs, and ASICs. + +rapids_test +*********** + +To help RAPIDS projects utilize all GPUs on a machine when running tests, the ``rapids-cmake`` project offers a suite of commands to simplify the process. +These commands simplify GPU detection, setting up resource specification files, specifying test requirements, and setting the active CUDA GPU. + +Machine GPU Detection +********************* + +The key component of CTest resource allocation is having an accurate representation of the hardware that exists on the developer's machine. +The :cmake:command:`rapids_test_init` function will do system introspection to determine the number of GPUs on the current machine and generate a resource allocation JSON file representing these GPUs. + +.. code-block:: cmake + + include(${CMAKE_BINARY_DIR}/RAPIDS.cmake) + + include(rapids-test) + + enable_testing() + rapids_test_init() + +The CTest resource allocation specification isn't limited to representing GPUs as a single unit. +Instead it allows the JSON file to specify the capacity (slots) that each GPU has. +In the case of rapids-cmake we always represent each GPU as having 100 slots allowing projects to think in total percentages when calculating requirements. + + +Specifying Tests GPU Requirements +********************************* +As discussed above, each CMake test needs to specify the GPU resources they require to allow CTest to properly partition GPUs given the CTest parallel level. +The easiest path for for developers is to use the :cmake:command:`rapids_test_add` which wraps each execution in a wrapper script that sets the CUDA visible devices, making tests only see the allocated device(s). + +For example below we have three tests, two which can run concurrently on the same GPU and one that requires a full GPU. +This specification will allow all three tests to run concurrently when a machine has 2+ GPUs with no modification of the tests! + +.. code-block:: cmake + + include(rapids-test) + + enable_testing() + rapids_test_init() + + add_executable( cuda_test test.cu ) + rapids_test_add(NAME test_small_alloc COMMAND cuda_test 50 GPUS 1 PERCENT 10) + rapids_test_add(NAME test_medium_alloc COMMAND cuda_test 100 GPUS 1 PERCENT 20) + rapids_test_add(NAME test_very_large_alloc COMMAND cuda_test 10000 GPUS 1) + + +Multi GPU Tests +*************** +The :cmake:command:`rapids_test_add` command also supports tests that require multiple GPU bindings. +In that case you will need to request two (or more) GPUs with a full allocation like this: + +.. code-block:: cmake + + include(rapids-test) + + enable_testing() + rapids_test_init() + + add_executable( cuda_test test.cu ) + rapids_test_add(NAME multi_gpu COMMAND cuda_test GPUS 3) + +Due to how CTest does allocations if you need distinct GPUs you need to request a percentage of 51% or higher. +Otherwise you have a chance for multiple allocations to be placed on the same GPU. + +When rapids-cmake test wrapper is insufficient +********************************************** + +At times the approach of using wrapper scripts is insufficient, usually due to using existing test wrappers. + +As discussed above, each CMake test still needs to specify the GPU resources they require to allow CTest to properly partition GPUs given the CTest parallel level. +But in those cases the tests themselves will need to parse the CTest environment variables to extract what GPUs they should run on. + +For the CMake side you can use :cmake:command:`rapids_test_gpu_requirements` to specify the requirements: + +.. code-block:: cmake + + include(rapids-test) + + enable_testing() + rapids_test_init() + + add_executable( cuda_test test.cu ) + target_link_libraries( cuda_test PRIVATE RAPIDS::test ) + + add_test(NAME test_small_alloc COMMAND cuda_test 50) + rapids_test_gpu_requirements(test_small_alloc GPUS 1 PERCENT 10) + +Now in the C++ you need to parse the relevant `CTEST_RESOURCE_GROUP` environment variables. +To simplify the process, here is some helper C++ code that will do the heavy lifting for you: + +.. literalinclude:: cpp_code_snippets/rapids_cmake_ctest_allocation.hpp + :language: cpp + +.. literalinclude:: cpp_code_snippets/rapids_cmake_ctest_allocation.cpp + :language: cpp diff --git a/docs/index.rst b/docs/index.rst index b770cc5a..fe4aa215 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,6 +15,7 @@ fixes easier. api.rst basics.rst dependency_tracking.rst + hardware_resources_and_testing.rst diff --git a/rapids-cmake/rapids-test.cmake b/rapids-cmake/rapids-test.cmake new file mode 100644 index 00000000..2edbff26 --- /dev/null +++ b/rapids-cmake/rapids-test.cmake @@ -0,0 +1,21 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/test/init.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/test/add.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/test/gpu_requirements.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/test/install_relocatable.cmake) diff --git a/rapids-cmake/test/add.cmake b/rapids-cmake/test/add.cmake new file mode 100644 index 00000000..607f3280 --- /dev/null +++ b/rapids-cmake/test/add.cmake @@ -0,0 +1,149 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_add +--------------- + +.. versionadded:: v23.04.00 + +States how many GPUs and what percent of each a test requires. + + .. code-block:: cmake + + rapids_test_add(NAME COMMAND [...] + [GPUS [PERCENT ]] + [INSTALL_COMPONENT_SET ] + [WORKING_DIRECTORY ]) + +Add a test called `` which will be executed with a given GPU +resource allocation. + +When combined with :cmake:command:`rapids_test_init` informs CTest what +resources should be allocated to a test so that when testing in parallel +oversubscription doesn't occur. Without this information user execution of +CTest with high parallel levels will cause multiple tests to run on the +same GPU and quickly exhaust all memory. + +``COMMAND`` + Specify the test command-line. If specifies an executable target + (created by add_executable()) it will automatically be replaced by the location of the + executable created at build time. + +``GPUS`` + State how many GPUs this test requires. Allows CTest to not over-subscribe + a machine's hardware. + + If no value is provided, the test is considered to not use any GPUs + +``PERCENT`` + By default if no percent is provided, 100 is used. + State how much of each GPU this test requires. + +``INSTALL_COMPONENT_SET`` + Record which component that the underlying executable for the test will be installed by. This is used + by :cmake:command:`rapids_test_install_relocatable` to allow for execution of the installed tests + by ctest + +``WORKING_DIRECTORY`` + Specify the working directory in which to execute the test. If not specified the test will + be run with the current working directory set to the value of :cmake:variable:`CMAKE_CURRENT_BINARY_DIR `. + + +#]=======================================================================] +# cmake-lint: disable=R0915 +function(rapids_test_add) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.add") + + set(options) + set(one_value NAME WORKING_DIRECTORY GPUS PERCENT INSTALL_COMPONENT_SET) + set(multi_value COMMAND) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + if(NOT DEFINED _RAPIDS_TEST_NAME) + message(FATAL_ERROR "rapids_add_test called without a name") + endif() + + if(NOT DEFINED _RAPIDS_TEST_COMMAND) + message(FATAL_ERROR "rapids_add_test called without a command") + endif() + + list(POP_FRONT _RAPIDS_TEST_COMMAND command_or_target) + set(args "${_RAPIDS_TEST_COMMAND}") + + set(command ${command_or_target}) + if(TARGET ${command_or_target}) + set(command "$") + endif() + + if(NOT DEFINED _RAPIDS_TEST_WORKING_DIRECTORY) + set(_RAPIDS_TEST_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + # Provide a copy of the test runner in the binary directory so that tests still can be executed if + # for some reason rapids-cmake src has been removed. + set(_rapids_run_gpu_test_script "${PROJECT_BINARY_DIR}/rapids-cmake/run_gpu_test.cmake") + set(_rapids_run_gpu_test_script_for_install "./run_gpu_test.cmake") + if(NOT EXISTS "${_rapids_run_gpu_test_script}") + file(COPY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake" + DESTINATION "${PROJECT_BINARY_DIR}/rapids-cmake/") + endif() + + add_test(NAME ${_RAPIDS_TEST_NAME} + COMMAND ${CMAKE_COMMAND} "-Dcommand_to_run=${command}" "-Dcommand_args=${args}" -P + "${_rapids_run_gpu_test_script}" + WORKING_DIRECTORY "${_RAPIDS_TEST_WORKING_DIRECTORY}") + + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gpu_requirements.cmake) + if(DEFINED _RAPIDS_TEST_GPUS) + rapids_test_gpu_requirements(${_RAPIDS_TEST_NAME} GPUS ${_RAPIDS_TEST_GPUS} + PERCENT ${_RAPIDS_TEST_PERCENT}) + endif() + + if(_RAPIDS_TEST_INSTALL_COMPONENT_SET) + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/record_test_component.cmake) + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/record_test_command.cmake) + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/record_install.cmake) + + if(NOT TARGET rapids_test_install_${_RAPIDS_TEST_INSTALL_COMPONENT_SET}) + add_library(rapids_test_install_${_RAPIDS_TEST_INSTALL_COMPONENT_SET} INTERFACE) + endif() + + if(TARGET ${command_or_target}) + get_target_property(output_name ${command_or_target} OUTPUT_NAME) + if(output_name) + set(command_for_install "./${output_name}") + else() + set(command_for_install "./${command_or_target}") + endif() + rapids_test_record_install(TARGET ${command_or_target} COMPONENT + ${_RAPIDS_TEST_INSTALL_COMPONENT_SET}) + else() + set(command_for_install ${command_or_target}) + endif() + rapids_test_record_test_component(NAME ${_RAPIDS_TEST_NAME} COMPONENT + ${_RAPIDS_TEST_INSTALL_COMPONENT_SET}) + rapids_test_record_test_command(NAME + ${_RAPIDS_TEST_NAME} + COMMAND + cmake + "-Dcommand_to_run=${command_for_install}" + "-Dcommand_args=${args}" + -P + "${_rapids_run_gpu_test_script_for_install}") + endif() +endfunction() diff --git a/rapids-cmake/test/detail/generate_resource_spec.cpp b/rapids-cmake/test/detail/generate_resource_spec.cpp new file mode 100644 index 00000000..3c1dcf57 --- /dev/null +++ b/rapids-cmake/test/detail/generate_resource_spec.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +struct version { + int major = 1; + int minor = 0; +}; + +struct gpu { + gpu(int i) : id{i} {}; + gpu(int i, const cudaDeviceProp& prop) : id{i}, memory{prop.totalGlobalMem}, slots{100} {} + int id = 0; + size_t memory = 0; + int slots = 0; +}; + +struct local { + local() + { + int nDevices = 0; + cudaGetDeviceCount(&nDevices); + if (nDevices == 0) { + gpus.emplace_back(0); + } else { + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaGetDeviceProperties(&prop, i); + gpus.emplace_back(i, prop); + } + } + } + std::vector gpus; +}; + +// A hard-coded JSON printer, but it gets the job done +void to_json(std::ostream& buffer, version const& v) +{ + buffer << "\"version\": {\"major\": " << v.major << ", \"minor\": " << v.minor << "}"; +} +void to_json(std::ostream& buffer, gpu const& g) +{ + buffer << "\t\t{\"id\": \"" << g.id << "\", \"slots\": " << g.slots << "}"; +} +void to_json(std::ostream& buffer, local const& l) +{ + buffer << "\"local\": [{\n"; + buffer << "\t\"gpus\": [\n"; + for (int i = 0; i < l.gpus.size(); ++i) { + to_json(buffer, l.gpus[i]); + if (i != (l.gpus.size() - 1)) { buffer << ","; } + buffer << "\n"; + } + buffer << "\t]\n"; + buffer << "}]\n"; +} + +int main(int, char**) +{ + version v{1, 0}; + local l; + + std::cout << "{\n"; + to_json(std::cout, v); + std::cout << ",\n"; + to_json(std::cout, l); + std::cout << "}" << std::endl; + return 0; +} diff --git a/rapids-cmake/test/detail/record_install.cmake b/rapids-cmake/test/detail/record_install.cmake new file mode 100644 index 00000000..9e8216b4 --- /dev/null +++ b/rapids-cmake/test/detail/record_install.cmake @@ -0,0 +1,43 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_record_install +-------------------------- + +.. versionadded:: v23.04.00 + +Record that the provided target should have install rules specified when +:cmake:command:`rapids_test_install_relocatable` is called with the given component. + + .. code-block:: cmake + + rapids_test_record_install(TARGET COMPONENT ) + +#]=======================================================================] +function(rapids_test_record_install) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.record_install") + + set(options) + set(one_value TARGET COMPONENT) + set(multi_value) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + set(component ${_RAPIDS_TEST_COMPONENT}) + set_property(TARGET rapids_test_install_${component} APPEND PROPERTY "TARGETS_TO_INSTALL" + "${_RAPIDS_TEST_TARGET}") +endfunction() diff --git a/rapids-cmake/test/detail/record_test_command.cmake b/rapids-cmake/test/detail/record_test_command.cmake new file mode 100644 index 00000000..4b740a1f --- /dev/null +++ b/rapids-cmake/test/detail/record_test_command.cmake @@ -0,0 +1,40 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_record_test_command +------------------------------- + +.. versionadded:: v23.04.00 + +Record the test command that needs to run when executed via ctest after installation + + .. code-block:: cmake + + rapids_test_record_test_command(NAME COMMAND command ...) + +#]=======================================================================] +function(rapids_test_record_test_command) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.record_test_command") + + set(options) + set(one_value NAME) + set(multi_value COMMAND) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + set_property(TEST ${_RAPIDS_TEST_NAME} PROPERTY INSTALL_COMMAND "${_RAPIDS_TEST_COMMAND}") +endfunction() diff --git a/rapids-cmake/test/detail/record_test_component.cmake b/rapids-cmake/test/detail/record_test_component.cmake new file mode 100644 index 00000000..cd68302c --- /dev/null +++ b/rapids-cmake/test/detail/record_test_component.cmake @@ -0,0 +1,42 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_record_test_component +--------------------------------- + +.. versionadded:: v23.04.00 + +Record what component a test is part of + + .. code-block:: cmake + + rapids_test_record_test_component(NAME COMPONENT ) + +#]=======================================================================] +function(rapids_test_record_test_component) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.record_test_component") + + set(options) + set(one_value NAME COMPONENT) + set(multi_value) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + set(component ${_RAPIDS_TEST_COMPONENT}) + set_property(TARGET rapids_test_install_${component} APPEND PROPERTY "TESTS_TO_RUN" + "${_RAPIDS_TEST_NAME}") +endfunction() diff --git a/rapids-cmake/test/detail/run_gpu_test.cmake b/rapids-cmake/test/detail/run_gpu_test.cmake new file mode 100644 index 00000000..1cd11d93 --- /dev/null +++ b/rapids-cmake/test/detail/run_gpu_test.cmake @@ -0,0 +1,33 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.23.1) + +if(DEFINED ENV{CTEST_RESOURCE_GROUP_COUNT}) + # cmake-lint: disable=E1120 + foreach(index RANGE 0 ${CTEST_RESOURCE_GROUP_COUNT}) + set(allocation $ENV{CTEST_RESOURCE_GROUP_${index}_GPUS}) + if(DEFINED allocation) + # strings look like "id:value,slots:value" so let's make a super lazy parser by deleting `id:` + # and replacing `,slots:` with `;` so we have a list with two items. + string(REPLACE "id:" "" allocation "${allocation}") + string(REPLACE ",slots:" ";" allocation "${allocation}") + list(GET allocation 0 device_ids) + list(GET allocation 1 percent) + set(ENV{CUDA_VISIBLE_DEVICES} ${device_ids}) + endif() + endforeach() +endif() +execute_process(COMMAND ${command_to_run} ${command_args} COMMAND_ECHO STDOUT) diff --git a/rapids-cmake/test/generate_resource_spec.cmake b/rapids-cmake/test/generate_resource_spec.cmake new file mode 100644 index 00000000..6f883888 --- /dev/null +++ b/rapids-cmake/test/generate_resource_spec.cmake @@ -0,0 +1,94 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_generate_resource_spec +---------------------------------- + +.. versionadded:: v23.04.00 + +Generates a JSON resource specification file representing the machine's GPUs +using system introspection. + + .. code-block:: cmake + + rapids_test_generate_resource_spec( DESTINATION filepath ) + +Generates a JSON resource specification file representing the machine's GPUs +using system introspection. This will allow CTest to schedule multiple +single-GPU tests in parallel on multi-GPU machines. + +For the majority of projects :cmake:command:`rapids_test_init` should be used. +This command should be used directly projects that require multiple spec +files to be generated. + +``DESTINATION`` + Location that the JSON output from the detection should be written to + +.. note:: + Unlike rapids_test_init this doesn't set CTEST_RESOURCE_SPEC_FILE + +#]=======================================================================] +function(rapids_test_generate_resource_spec DESTINATION filepath) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.generate_resource_spec") + + if(NOT DEFINED CMAKE_CUDA_COMPILER AND NOT DEFINED CMAKE_CXX_COMPILER) + message(FATAL_ERROR "rapids_test_generate_resource_spec Requires the CUDA or C++ language to be enabled." + ) + endif() + + set(gpu_json_contents + [=[ +{ +"version": {"major": 1, "minor": 0}, +"local": [{ + "gpus": [{"id":"0", "slots": 100}] +}] +} +]=]) + + set(eval_file ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/generate_resource_spec.cpp) + set(eval_exe ${PROJECT_BINARY_DIR}/rapids-cmake/generate_ctest_json) + set(error_file ${PROJECT_BINARY_DIR}/rapids-cmake/detect_gpus.stderr.log) + + if(NOT EXISTS "${eval_exe}") + find_package(CUDAToolkit REQUIRED) + file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/rapids-cmake/") + + set(compile_options "-I${CUDAToolkit_INCLUDE_DIRS}") + set(link_options ${CUDA_cudart_LIBRARY}) + set(compiler "${CMAKE_CXX_COMPILER}") + if(NOT DEFINED CMAKE_CXX_COMPILER) + set(compiler "${CMAKE_CUDA_COMPILER}") + endif() + + execute_process(COMMAND "${compiler}" "${eval_file}" ${compile_options} ${link_options} -o + "${eval_exe}" OUTPUT_VARIABLE compile_output + ERROR_VARIABLE compile_output COMMAND_ECHO STDOUT) + endif() + + if(NOT EXISTS "${eval_exe}") + message(STATUS "rapids_test_generate_resource_spec failed to build detection executable, presuming 1 GPU." + ) + message(STATUS "rapids_test_generate_resource_spec compile failure details are ${compile_output}" + ) + file(WRITE "${filepath}" "${gpu_json_contents}") + else() + execute_process(COMMAND ${eval_exe} OUTPUT_FILE "${filepath}") + endif() + +endfunction() diff --git a/rapids-cmake/test/gpu_requirements.cmake b/rapids-cmake/test/gpu_requirements.cmake new file mode 100644 index 00000000..7e9cedc3 --- /dev/null +++ b/rapids-cmake/test/gpu_requirements.cmake @@ -0,0 +1,92 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_gpu_requirements +---------------------------- + +.. versionadded:: v23.04.00 + +States how many GPUs and what percent of each a test requires. + + .. code-block:: cmake + + rapids_test_gpu_requirements( test_name GPUS [PERCENT ]) + +This function should only be used when :cmake:command:`rapids_test_add` is +insufficient due to the rapids-cmake test wrappers not working for your +project. + +When combined with :cmake:command:`rapids_test_init` informs CTest what +resources should be allocated to a test so that when testing in parallel +oversubscription doesn't occur. Without this information user execution of +CTest with high parallel levels will cause multiple tests to run on the +same GPU and quickly exhaust all memory. + + +``GPUS`` + State how many GPUs this test requires. Allows CTest to not over-subscribe + a machine's hardware. + + Any integer value >= 0 is supported + +``PERCENT`` + State how much of each GPU this test requires. In general 100, 50, and 20 + are commonly used values. By default if no percent is provided, 100 is + used. + + Any integer value >= 0 and <= 100 is supported + + Default value of 100 + +#]=======================================================================] +function(rapids_test_gpu_requirements test_name) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.gpu_requirements") + + set(options) + set(one_value GPUS PERCENT) + set(multi_value) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + if(DEFINED _RAPIDS_TEST_PERCENT AND NOT DEFINED _RAPIDS_TEST_GPUS) + message(FATAL_ERROR "rapids_test_gpu_requirements requires the GPUS option to be provided when PERCENT is" + ) + endif() + + set(gpus 0) + if(DEFINED _RAPIDS_TEST_GPUS) + set(gpus ${_RAPIDS_TEST_GPUS}) + endif() + + set(percent 100) + if(DEFINED _RAPIDS_TEST_PERCENT) + set(percent ${_RAPIDS_TEST_PERCENT}) + endif() + + # verify that gpu and percent are withing the allowed bounds + if(NOT gpus GREATER_EQUAL 0) + message(FATAL_ERROR "rapids_test_gpu_requirements requires a numeric GPUS value [0-N].") + endif() + if(NOT (percent GREATER_EQUAL 1 AND percent LESS_EQUAL 100)) + message(FATAL_ERROR "rapids_test_gpu_requirements requires a numeric PERCENT value [1-100].") + endif() + + if(gpus AND percent) + set_property(TEST ${test_name} PROPERTY RESOURCE_GROUPS "${gpus},gpus:${percent}") + endif() + +endfunction() diff --git a/rapids-cmake/test/init.cmake b/rapids-cmake/test/init.cmake new file mode 100644 index 00000000..cb0df2c6 --- /dev/null +++ b/rapids-cmake/test/init.cmake @@ -0,0 +1,64 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_init +---------------- + +.. versionadded:: v23.04.00 + +Establish necessary components for CTest GPU resource allocation to allow +for parallel tests. + + .. code-block:: cmake + + rapids_test_init( ) + +Generates a JSON resource specification file representing the machine's GPUs +using system introspection. This will allow CTest to schedule multiple +single-GPU or multi-GPU tests in parallel on multi-GPU machines. + +For tests to execute correctly they will need to use the +:cmake:command:`rapids_test_add` to register GPU requirements: + +.. code-block:: cmake + + enable_testing() + include(rapids-test) + rapids_test_init() + + add_executable( test_example test.cu ) + rapids_test_add(NAME single_gpu_alloc COMMAND test_example GPUS 1) + rapids_test_add(NAME two_gpu_alloc COMMAND test_example GPUS 2) + +Result Variables +^^^^^^^^^^^^^^^^ + :cmake:variable:`CTEST_RESOURCE_SPEC_FILE` will be set to the generated + JSON file if not already set + +#]=======================================================================] +function(rapids_test_init) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.init") + + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/generate_resource_spec.cmake) + rapids_test_generate_resource_spec(DESTINATION "${PROJECT_BINARY_DIR}/resource_spec.json") + + if(NOT CTEST_RESOURCE_SPEC_FILE) + set(CTEST_RESOURCE_SPEC_FILE "${PROJECT_BINARY_DIR}/resource_spec.json" PARENT_SCOPE) + endif() + +endfunction() diff --git a/rapids-cmake/test/install_relocatable.cmake b/rapids-cmake/test/install_relocatable.cmake new file mode 100644 index 00000000..7b024b4e --- /dev/null +++ b/rapids-cmake/test/install_relocatable.cmake @@ -0,0 +1,112 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +#[=======================================================================[.rst: +rapids_test_install_relocatable +------------------------------- + +.. versionadded:: v23.04.00 + +Install the needed `ctest` infrastructure to allow installed tests to be run +by `ctest` in parallel with GPU awareness. + + .. code-block:: cmake + + rapids_test_install_relocatable(INSTALL_COMPONENT_SET + DESTINATION + [EXCLUDE_FROM_ALL]) + +Add ... + +``INSTALL_COMPONENT_SET`` + Record which test component infrastructure to be installed + +``DESTINATION`` + Relative path from the `CMAKE_INSTALL_PREFIX` to install the infrastructure. + This needs to be the same directory as the test executables + +``EXCLUDE_FROM_ALL`` + State that these install rules shouldn't be part of the default install set, and + instead must be explicitly installed. + + +#]=======================================================================] +function(rapids_test_install_relocatable) + list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.install_relocatable") + + set(options EXCLUDE_FROM_ALL) + set(one_value INSTALL_COMPONENT_SET DESTINATION) + set(multi_value) + cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) + + set(to_exclude) + if(_RAPIDS_TEST_EXCLUDE_FROM_ALL) + set(to_exclude EXCLUDE_FROM_ALL) + endif() + + set(component ${_RAPIDS_TEST_INSTALL_COMPONENT_SET}) + if(NOT TARGET rapids_test_install_${component}) + message(FATAL_ERROR "No install component set [${component}] can be found") + endif() + + get_target_property(targets_to_install rapids_test_install_${component} TARGETS_TO_INSTALL) + get_target_property(tests_to_run rapids_test_install_${component} TESTS_TO_RUN) + + set(content + [==[ + set(CTEST_SCRIPT_DIRECTORY ".") + set(CTEST_RESOURCE_SPEC_FILE "./resource_spec.json") + execute_process(COMMAND ./generate_ctest_json OUTPUT_FILE "${CTEST_RESOURCE_SPEC_FILE}") + ]==]) + + foreach(test IN LISTS tests_to_run) + get_test_property(${test} INSTALL_COMMAND command) + get_test_property(${test} RESOURCE_GROUPS resources) + get_test_property(${test} LABELS labels) + string(APPEND content "add_test([=[${test}]=] ${command})\n") + if(resources) + string(APPEND content + "set_tests_properties([=[${test}]=] PROPERTIES RESOURCE_GROUPS ${resources})\n") + endif() + if(labels) + string(APPEND content "set_tests_properties([=[${test}]=] PROPERTIES LABELS ${labels})\n") + endif() + endforeach() + + set(test_launcher_file + "${CMAKE_CURRENT_BINARY_DIR}/rapids-cmake/${_RAPIDS_TEST_INSTALL_COMPONENT_SET}/CTestTestfile.cmake.to_install" + ) + file(WRITE "${test_launcher_file}" "${content}") + install(FILES "${test_launcher_file}" + COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} + DESTINATION ${_RAPIDS_TEST_DESTINATION} + RENAME "CTestTestfile.cmake" + ${to_exclude}) + + # We need to install the rapids-test gpu detector, and the json script we also need to write out / + # install the new CTestTestfile.cmake + install(PROGRAMS "${PROJECT_BINARY_DIR}/rapids-cmake/generate_ctest_json" + COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} DESTINATION ${_RAPIDS_TEST_DESTINATION} + ${to_exclude}) + install(FILES "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake" + COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} DESTINATION ${_RAPIDS_TEST_DESTINATION} + ${to_exclude}) + if(targets_to_install) + install(TARGETS ${targets_to_install} COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} + DESTINATION ${_RAPIDS_TEST_DESTINATION} ${to_exclude}) + endif() +endfunction() diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index 10f36305..66152456 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -19,6 +19,7 @@ project(rapids-cmake-testing LANGUAGES NONE) enable_testing() include(utils/cmake_config_test.cmake) +include(utils/cmake_ctest_test.cmake) include(utils/cmake_build_test.cmake) add_subdirectory(cmake) @@ -26,6 +27,10 @@ add_subdirectory(cuda) add_subdirectory(export) add_subdirectory(find) +include("${CMAKE_CURRENT_SOURCE_DIR}/utils/determine_gpu_count.cmake") +determine_gpu_count() +add_subdirectory(test) + option(RAPIDS_CMAKE_ENABLE_DOWNLOAD_TESTS "Enable tests that require downloads" ON) if(RAPIDS_CMAKE_ENABLE_DOWNLOAD_TESTS) # Setup and fill the cpm cache, and specify CPM_SOURCE_CACHE diff --git a/testing/test/CMakeLists.txt b/testing/test/CMakeLists.txt new file mode 100644 index 00000000..dd0c4444 --- /dev/null +++ b/testing/test/CMakeLists.txt @@ -0,0 +1,58 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +add_cmake_config_test( rapids-test.cmake ) + +add_cmake_config_test(generate_resource_spec-no-gpus.cmake) +add_cmake_config_test(generate_resource_spec-simple.cmake) + +set(percent_error_message "rapids_test_gpu_requirements requires a numeric PERCENT value [1-100].") +set(gpu_error_message "rapids_test_gpu_requirements GPUS requires a numeric value") +set(gpu_missing_message "rapids_test_gpu_requirements requires the GPUS option to be provided") +add_cmake_config_test(gpu_requirements-char-percent.cmake SHOULD_FAIL "${percent_error_message}") +add_cmake_config_test(gpu_requirements-char-gpu.cmake SHOULD_FAIL "${gpu_error_message}") +add_cmake_config_test(gpu_requirements-zero-gpu.cmake) +add_cmake_config_test(gpu_requirements-max-percent.cmake) +add_cmake_config_test(gpu_requirements-min-percent.cmake) +add_cmake_config_test(gpu_requirements-multi.cmake) +add_cmake_config_test(gpu_requirements-negative-percent.cmake SHOULD_FAIL "${percent_error_message}") +add_cmake_config_test(gpu_requirements-negative-gpu.cmake SHOULD_FAIL "${gpu_error_message}") +add_cmake_config_test(gpu_requirements-no-gpus.cmake SHOULD_FAIL "${gpu_missing_message}") +add_cmake_config_test(gpu_requirements-no-percent.cmake) +add_cmake_config_test(gpu_requirements-over-max-percent.cmake SHOULD_FAIL "${percent_error_message}") +add_cmake_config_test(gpu_requirements-single.cmake) +add_cmake_config_test(gpu_requirements-zero-percent.cmake SHOULD_FAIL "${percent_error_message}") + +add_cmake_config_test(init-existing-specfile.cmake) +add_cmake_config_test(init-simple.cmake) + +set(wrong_component_message "No install component set [wrong_component] can be found") +add_cmake_config_test(install_relocatable-labels.cmake) +add_cmake_config_test(install_relocatable-simple.cmake) +add_cmake_config_test(install_relocatable-wrong-component.cmake SHOULD_FAIL "${wrong_component_message}") + +add_cmake_ctest_test(add-impossible-allocation SHOULD_FAIL "Insufficient resources for test") +add_cmake_config_test(add-with-install-component.cmake) +add_cmake_config_test(add-with-no-gpus.cmake) +if(RAPIDS_CMAKE_TESTING_GPU_COUNT GREATER 0) + add_cmake_ctest_test(add-allocation-simple) + add_cmake_ctest_test(add-multi-allocations-same-gpu) + add_cmake_ctest_test(add-multi-jobs-single-gpu) + add_cmake_ctest_test(no_add-with-cpp-handler-from-docs) + add_cmake_ctest_test(no_add-with-no-resource-spec) +endif() +if(RAPIDS_CMAKE_TESTING_GPU_COUNT GREATER 1) + add_cmake_ctest_test(add-single-job-multi-gpu) +endif() diff --git a/testing/test/add-allocation-simple/CMakeLists.txt b/testing/test/add-allocation-simple/CMakeLists.txt new file mode 100644 index 00000000..06b5b331 --- /dev/null +++ b/testing/test/add-allocation-simple/CMakeLists.txt @@ -0,0 +1,31 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +add_executable(verify_alloc main.cu) + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc GPUS 1) + +# Validate that the test runs correctly +set_tests_properties(simple_test + PROPERTIES PASS_REGULAR_EXPRESSION "Seeing 1 GPU devices" + ) diff --git a/testing/test/add-allocation-simple/main.cu b/testing/test/add-allocation-simple/main.cu new file mode 100644 index 00000000..65c06c73 --- /dev/null +++ b/testing/test/add-allocation-simple/main.cu @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int main() +{ + // Verify we only have a single GPU visible to us + int nDevices = 0; + cudaGetDeviceCount(&nDevices); + + std::cout << "Seeing " << nDevices << " GPU devices" << std::endl; + + if (nDevices == 0 || nDevices > 3) { return 1; } + return 0; +} diff --git a/testing/test/add-impossible-allocation/CMakeLists.txt b/testing/test/add-impossible-allocation/CMakeLists.txt new file mode 100644 index 00000000..28ad8040 --- /dev/null +++ b/testing/test/add-impossible-allocation/CMakeLists.txt @@ -0,0 +1,26 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +add_executable(verify_alloc main.cu) + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc simple_test GPUS 25) diff --git a/testing/test/add-impossible-allocation/main.cu b/testing/test/add-impossible-allocation/main.cu new file mode 100644 index 00000000..b62fcc1e --- /dev/null +++ b/testing/test/add-impossible-allocation/main.cu @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int main() { return 0; } diff --git a/testing/test/add-multi-allocations-same-gpu/CMakeLists.txt b/testing/test/add-multi-allocations-same-gpu/CMakeLists.txt new file mode 100644 index 00000000..6c5e7fbf --- /dev/null +++ b/testing/test/add-multi-allocations-same-gpu/CMakeLists.txt @@ -0,0 +1,31 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +add_executable(verify_alloc main.cu) + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc GPUS 10 PERCENT 1) + +# Validate that the test runs correctly +set_tests_properties(simple_test + PROPERTIES PASS_REGULAR_EXPRESSION "Seeing at least a single GPU" + ) diff --git a/testing/test/add-multi-allocations-same-gpu/main.cu b/testing/test/add-multi-allocations-same-gpu/main.cu new file mode 100644 index 00000000..00bd365e --- /dev/null +++ b/testing/test/add-multi-allocations-same-gpu/main.cu @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int main() +{ + // Very we only have a single GPU visible to us + int nDevices = 0; + cudaGetDeviceCount(&nDevices); + + if (nDevices == 0) { return 1; } + std::cout << "Seeing at least a single GPU" << std::endl; + return 0; +} diff --git a/testing/test/add-multi-jobs-single-gpu/CMakeLists.txt b/testing/test/add-multi-jobs-single-gpu/CMakeLists.txt new file mode 100644 index 00000000..29bc4a77 --- /dev/null +++ b/testing/test/add-multi-jobs-single-gpu/CMakeLists.txt @@ -0,0 +1,35 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +find_package(CUDAToolkit REQUIRED) + +add_executable(verify_multi_concurrent main.cu) +target_link_libraries(verify_multi_concurrent PRIVATE CUDA::cudart) +target_include_directories(verify_multi_concurrent PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") +target_compile_definitions(verify_multi_concurrent PRIVATE "BINARY_DIR=${CMAKE_BINARY_DIR}") + +enable_testing() + +foreach(v RANGE 5) + # this way all our tests can reside on the same gpu + rapids_test_add(NAME concurrent_test_${v} COMMAND verify_multi_concurrent ${v} GPUS 1 PERCENT 1${v}) +endforeach() diff --git a/testing/test/add-multi-jobs-single-gpu/main.cu b/testing/test/add-multi-jobs-single-gpu/main.cu new file mode 100644 index 00000000..73b38224 --- /dev/null +++ b/testing/test/add-multi-jobs-single-gpu/main.cu @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#include "../detail/file_locker.hpp" + +int main(int argc, char** argv) +{ + const constexpr int min_lock_id = 0; + const constexpr int max_lock_id = 5; + + // Lock our sentinel file + auto my_id = std::stoi(argv[1]); + auto lock = ctest_lock(my_id); + + // verify all sentinel files are locked + auto checker = [my_id](int lock_state, int i) { + bool valid_lock_state = false; + if (i == my_id) { + // we have this file locked + valid_lock_state = (lock_state == 0); + } else { + // some other process has this file locked + valid_lock_state = (lock_state == -1); + } + std::cout << i << " lock_state: " << lock_state << " valid " << valid_lock_state << std::endl; + return valid_lock_state; + }; + bool all_locked = validate_locks(checker, min_lock_id, max_lock_id); + // unlock and return + unlock(lock); + return (all_locked) ? 0 : 1; +} diff --git a/testing/test/add-single-job-multi-gpu/CMakeLists.txt b/testing/test/add-single-job-multi-gpu/CMakeLists.txt new file mode 100644 index 00000000..39e27284 --- /dev/null +++ b/testing/test/add-single-job-multi-gpu/CMakeLists.txt @@ -0,0 +1,26 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +add_executable(verify_alloc main.cu) + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc GPUS 2 PERCENT 75) diff --git a/testing/test/add-single-job-multi-gpu/main.cu b/testing/test/add-single-job-multi-gpu/main.cu new file mode 100644 index 00000000..e3a9efba --- /dev/null +++ b/testing/test/add-single-job-multi-gpu/main.cu @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +int main() +{ + int nDevices = 0; + cudaGetDeviceCount(&nDevices); + + // We should have anywhere from 1 to 2 devices allocated + std::cout << "Seeing " << nDevices << " GPU devices" << std::endl; + + if (nDevices == 0 || nDevices > 2) { return 1; } + return 0; +} diff --git a/testing/test/add-with-install-component.cmake b/testing/test/add-with-install-component.cmake new file mode 100644 index 00000000..688305c9 --- /dev/null +++ b/testing/test/add-with-install-component.cmake @@ -0,0 +1,45 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) +include(${rapids-cmake-dir}/test/add.cmake) + +enable_language(CUDA) + +rapids_test_init() + +file(WRITE "${CMAKE_BINARY_DIR}/main.cu" "int main(){return 0;}") +add_executable(verify_alloc "${CMAKE_BINARY_DIR}/main.cu") + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc GPUS 1 INSTALL_COMPONENT_SET testing) + +# Verify that we have recorded `simple_test` as part of the `testing` component +get_target_property(names rapids_test_install_testing TESTS_TO_RUN) +if(NOT "simple_test" IN_LIST names) + message(FATAL_ERROR "Failed to record `simple_test` as part of the testing component") +endif() + +# Verify that `verify_alloc` is marked as to be installed +get_target_property(names rapids_test_install_testing TARGETS_TO_INSTALL) +if(NOT "verify_alloc" IN_LIST names) + message(FATAL_ERROR "Failed to record `verify_alloc` as a target to be installed in the testing component") +endif() + +# Verify we recorded some install command for `simple_test` +get_test_property(simple_test INSTALL_COMMAND install_command) +if(NOT install_command) + message(FATAL_ERROR "Failed to record the command to run `simple_test` after installing it") +endif() diff --git a/testing/test/add-with-no-gpus.cmake b/testing/test/add-with-no-gpus.cmake new file mode 100644 index 00000000..56219341 --- /dev/null +++ b/testing/test/add-with-no-gpus.cmake @@ -0,0 +1,32 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) +include(${rapids-cmake-dir}/test/add.cmake) + +enable_language(CUDA) + +rapids_test_init() + +file(WRITE "${CMAKE_BINARY_DIR}/main.cu" "int main(){return 0;}") +add_executable(verify_alloc "${CMAKE_BINARY_DIR}/main.cu") + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc INSTALL_COMPONENT_SET testing) + +get_test_property(simple_test RESOURCE_GROUPS value) +if(value) + message(FATAL_ERROR "Unexpected RESOURCE_GROUPS test property value(${value}) found, should not be set") +endif() diff --git a/testing/test/detail/file_locker.hpp b/testing/test/detail/file_locker.hpp new file mode 100644 index 00000000..52a94e75 --- /dev/null +++ b/testing/test/detail/file_locker.hpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#define DefineToString(a) define_to_str(a) +#define define_to_str(a) #a + +std::string lock_file_name(int tid) +{ + const static std::string dir = DefineToString(BINARY_DIR); + return std::string(dir + "/lock." + std::to_string(tid)); +} + +struct ctest_lock { + std::string file_name; + int fd; + + ctest_lock(int test_id) + { + this->file_name = lock_file_name(test_id); + this->fd = open(file_name.c_str(), O_RDWR | O_CREAT, S_IRGRP | S_IRWXU); + + int activeDevice = 0; + cudaGetDevice(&activeDevice); + cudaDeviceProp prop; + cudaGetDeviceProperties(&prop, activeDevice); + + auto deviceIdAsStr = std::to_string(prop.pciBusID); + write(fd, deviceIdAsStr.c_str(), deviceIdAsStr.size()); + lockf(fd, F_TLOCK, 0); + } +}; + +template +bool validate_locks(LockValidator lock_checker, int min_lock_id, int max_lock_id) +{ + using namespace std::chrono_literals; + + // barrier + // wait for all other tests to lock the respective sentinel file + std::this_thread::sleep_for(5000ms); + + int valid_count = 0; + for (int i = min_lock_id; i <= max_lock_id; ++i) { + auto path = lock_file_name(i); + auto fd = open(path.c_str(), O_RDONLY); + auto lock_state = lockf(fd, F_TEST, 0); + + bool valid_lock_state = lock_checker(lock_state, i); + if (valid_lock_state) { ++valid_count; } + } + // barrier again so nothing unlocks while other are checking + // for a lock + std::this_thread::sleep_for(2000ms); + + return (valid_count == ((max_lock_id + 1) - min_lock_id)); +} + +void unlock(ctest_lock& lock) { close(lock.fd); } diff --git a/testing/test/generate_resource_spec-no-gpus.cmake b/testing/test/generate_resource_spec-no-gpus.cmake new file mode 100644 index 00000000..1d7603bd --- /dev/null +++ b/testing/test/generate_resource_spec-no-gpus.cmake @@ -0,0 +1,37 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/generate_resource_spec.cmake) + +enable_language(CUDA) + +# Set the visible device list to invalid device ids so we have zero visible +set(ENV{CUDA_VISIBLE_DEVICES} -1) + +set(CTEST_RESOURCE_SPEC_FILE "sentinel file") +rapids_test_generate_resource_spec(DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/spec.json ) + +if(NOT CTEST_RESOURCE_SPEC_FILE STREQUAL "sentinel file") + message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE shouldn't be modified by calling rapids_test_generate_resource_spec") +endif() + +if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/spec.json") + message(FATAL_ERROR "rapids_test_ll generate_resource_spec failed to write out the requested spec file") +endif() + +file(READ "${CMAKE_CURRENT_BINARY_DIR}/spec.json" content) +if(NOT content MATCHES [=[.*{"id": "0", "slots": 0}.*]=]) + message(FATAL_ERROR "rapids_test_generate_resource_spec incorrectly detected a GPU") +endif() diff --git a/testing/test/generate_resource_spec-simple.cmake b/testing/test/generate_resource_spec-simple.cmake new file mode 100644 index 00000000..d7659cd3 --- /dev/null +++ b/testing/test/generate_resource_spec-simple.cmake @@ -0,0 +1,29 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/generate_resource_spec.cmake) + +enable_language(CUDA) + +set(CTEST_RESOURCE_SPEC_FILE "sentinel file") +rapids_test_generate_resource_spec(DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/spec.json ) + +if(NOT CTEST_RESOURCE_SPEC_FILE STREQUAL "sentinel file") + message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE shouldn't be modified by calling rapids_test_generate_resource_spec") +endif() + +if(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/spec.json") + message(FATAL_ERROR "rapids_test_generate_resource_spec failed to write out the requested spec file") +endif() diff --git a/testing/test/gpu_requirements-char-gpu.cmake b/testing/test/gpu_requirements-char-gpu.cmake new file mode 100644 index 00000000..83c3849a --- /dev/null +++ b/testing/test/gpu_requirements-char-gpu.cmake @@ -0,0 +1,19 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") +rapids_test_gpu_requirements(fake_test GPUS -1 PERCENT 100) diff --git a/testing/test/gpu_requirements-char-percent.cmake b/testing/test/gpu_requirements-char-percent.cmake new file mode 100644 index 00000000..70b86a70 --- /dev/null +++ b/testing/test/gpu_requirements-char-percent.cmake @@ -0,0 +1,19 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT abc) diff --git a/testing/test/gpu_requirements-max-percent.cmake b/testing/test/gpu_requirements-max-percent.cmake new file mode 100644 index 00000000..8e7ff25d --- /dev/null +++ b/testing/test/gpu_requirements-max-percent.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT 100) diff --git a/testing/test/gpu_requirements-min-percent.cmake b/testing/test/gpu_requirements-min-percent.cmake new file mode 100644 index 00000000..635f35ee --- /dev/null +++ b/testing/test/gpu_requirements-min-percent.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT 1) diff --git a/testing/test/gpu_requirements-multi.cmake b/testing/test/gpu_requirements-multi.cmake new file mode 100644 index 00000000..7c3797e3 --- /dev/null +++ b/testing/test/gpu_requirements-multi.cmake @@ -0,0 +1,25 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 12 PERCENT 25) + +get_test_property(fake_test RESOURCE_GROUPS value) +if(NOT value STREQUAL "12,gpus:25") + message(FATAL_ERROR "Unexpected RESOURCE_GROUPS test property value after rapids_test_gpu_requirements") +endif() diff --git a/testing/test/gpu_requirements-negative-gpu.cmake b/testing/test/gpu_requirements-negative-gpu.cmake new file mode 100644 index 00000000..71a9703b --- /dev/null +++ b/testing/test/gpu_requirements-negative-gpu.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS -2 PERCENT 1) diff --git a/testing/test/gpu_requirements-negative-percent.cmake b/testing/test/gpu_requirements-negative-percent.cmake new file mode 100644 index 00000000..76597bd6 --- /dev/null +++ b/testing/test/gpu_requirements-negative-percent.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 2 PERCENT -1) diff --git a/testing/test/gpu_requirements-no-gpus.cmake b/testing/test/gpu_requirements-no-gpus.cmake new file mode 100644 index 00000000..b3825846 --- /dev/null +++ b/testing/test/gpu_requirements-no-gpus.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test PERCENT 50) diff --git a/testing/test/gpu_requirements-no-percent.cmake b/testing/test/gpu_requirements-no-percent.cmake new file mode 100644 index 00000000..af63f97d --- /dev/null +++ b/testing/test/gpu_requirements-no-percent.cmake @@ -0,0 +1,25 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 9) + +get_test_property(fake_test RESOURCE_GROUPS value) +if(NOT value STREQUAL "9,gpus:100") + message(FATAL_ERROR "Unexpected RESOURCE_GROUPS test property value(${value}) after rapids_test_gpu_requirements") +endif() diff --git a/testing/test/gpu_requirements-over-max-percent.cmake b/testing/test/gpu_requirements-over-max-percent.cmake new file mode 100644 index 00000000..14f19a0f --- /dev/null +++ b/testing/test/gpu_requirements-over-max-percent.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT 101) diff --git a/testing/test/gpu_requirements-single.cmake b/testing/test/gpu_requirements-single.cmake new file mode 100644 index 00000000..6e269c2c --- /dev/null +++ b/testing/test/gpu_requirements-single.cmake @@ -0,0 +1,25 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT 4) + +get_test_property(fake_test RESOURCE_GROUPS value) +if(NOT value STREQUAL "1,gpus:4") + message(FATAL_ERROR "Unexpected RESOURCE_GROUPS test property value after rapids_test_gpu_requirements") +endif() diff --git a/testing/test/gpu_requirements-zero-gpu.cmake b/testing/test/gpu_requirements-zero-gpu.cmake new file mode 100644 index 00000000..1167263f --- /dev/null +++ b/testing/test/gpu_requirements-zero-gpu.cmake @@ -0,0 +1,19 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") +rapids_test_gpu_requirements(fake_test GPUS 0 PERCENT 100) diff --git a/testing/test/gpu_requirements-zero-percent.cmake b/testing/test/gpu_requirements-zero-percent.cmake new file mode 100644 index 00000000..4a74a530 --- /dev/null +++ b/testing/test/gpu_requirements-zero-percent.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/gpu_requirements.cmake) + +add_test(fake_test COMMAND "${CMAKE_COMMAND} -E echo") + +rapids_test_gpu_requirements(fake_test GPUS 1 PERCENT 0) diff --git a/testing/test/init-existing-specfile.cmake b/testing/test/init-existing-specfile.cmake new file mode 100644 index 00000000..c2672f3e --- /dev/null +++ b/testing/test/init-existing-specfile.cmake @@ -0,0 +1,25 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) + +enable_language(CUDA) + +set(CTEST_RESOURCE_SPEC_FILE "sentinel file") +rapids_test_init() + +if(NOT CTEST_RESOURCE_SPEC_FILE STREQUAL "sentinel file") + message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE shouldn't be modified if already set before calling rapids_test_init") +endif() diff --git a/testing/test/init-simple.cmake b/testing/test/init-simple.cmake new file mode 100644 index 00000000..97127257 --- /dev/null +++ b/testing/test/init-simple.cmake @@ -0,0 +1,28 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) + +enable_language(CUDA) + +rapids_test_init() + +if(NOT DEFINED CTEST_RESOURCE_SPEC_FILE) + message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE should be set after calling rapids_test_init") +endif() + +if(NOT EXISTS "${CTEST_RESOURCE_SPEC_FILE}") + message(FATAL_ERROR "CTEST_RESOURCE_SPEC_FILE should exist on disk after calling rapids_test_init") +endif() diff --git a/testing/test/install_relocatable-labels.cmake b/testing/test/install_relocatable-labels.cmake new file mode 100644 index 00000000..cadcb6cd --- /dev/null +++ b/testing/test/install_relocatable-labels.cmake @@ -0,0 +1,36 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) +include(${rapids-cmake-dir}/test/add.cmake) +include(${rapids-cmake-dir}/test/install_relocatable.cmake) + +enable_language(CUDA) +rapids_test_init() + +rapids_test_add(NAME verify_labels COMMAND ls GPUS 1 INSTALL_COMPONENT_SET testing) +set_tests_properties(verify_labels PROPERTIES LABELS "has_label") + +rapids_test_install_relocatable(INSTALL_COMPONENT_SET testing + DESTINATION bin/testing) + +set(generated_testfile "${CMAKE_CURRENT_BINARY_DIR}/rapids-cmake/testing/CTestTestfile.cmake.to_install") +file(READ "${generated_testfile}" contents) + +set(labels_match_string [===[PROPERTIES LABELS has_label]===]) +string(FIND "${contents}" "${labels_match_string}" is_found) +if(is_found EQUAL -1) + message(FATAL_ERROR "Failed to record the LABELS property") +endif() diff --git a/testing/test/install_relocatable-simple.cmake b/testing/test/install_relocatable-simple.cmake new file mode 100644 index 00000000..026d7e75 --- /dev/null +++ b/testing/test/install_relocatable-simple.cmake @@ -0,0 +1,45 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) +include(${rapids-cmake-dir}/test/add.cmake) +include(${rapids-cmake-dir}/test/install_relocatable.cmake) + +enable_language(CUDA) +rapids_test_init() + +rapids_test_add(NAME verify_ COMMAND ls GPUS 1 INSTALL_COMPONENT_SET testing) + +rapids_test_install_relocatable(INSTALL_COMPONENT_SET testing + DESTINATION bin/testing + EXCLUDE_FROM_ALL) + +set(generated_testfile "${CMAKE_CURRENT_BINARY_DIR}/rapids-cmake/testing/CTestTestfile.cmake.to_install") +file(READ "${generated_testfile}" contents) + + +set(add_test_match_strings [===[add_test([=[verify_]=] cmake;-Dcommand_to_run=ls;-Dcommand_args=;-P;./run_gpu_test.cmake)]===]) +foreach(item IN LISTS add_test_match_strings) + string(FIND "${contents}" ${item} is_found) + if(is_found EQUAL -1) + message(FATAL_ERROR "Failed to generate an installed `add_test` for verify_") + endif() +endforeach() + +set(properties_match_string [===[PROPERTIES RESOURCE_GROUPS 1,gpus:100]===]) +string(FIND "${contents}" ${properties_match_string} is_found) +if(is_found EQUAL -1) + message(FATAL_ERROR "Failed to generate an installed `GPU` requirements for verify_") +endif() diff --git a/testing/test/install_relocatable-wrong-component.cmake b/testing/test/install_relocatable-wrong-component.cmake new file mode 100644 index 00000000..80aaa962 --- /dev/null +++ b/testing/test/install_relocatable-wrong-component.cmake @@ -0,0 +1,26 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/test/init.cmake) +include(${rapids-cmake-dir}/test/install_relocatable.cmake) + +enable_language(CUDA) +rapids_test_init() + +rapids_test_install_relocatable(INSTALL_COMPONENT_SET wrong_component + DESTINATION bin/testing) +rapids_test_install_relocatable(INSTALL_COMPONENT_SET another_wrong_component + DESTINATION bin/testing + EXCLUDE_FROM_ALL) diff --git a/testing/test/no_add-with-cpp-handler-from-docs/CMakeLists.txt b/testing/test/no_add-with-cpp-handler-from-docs/CMakeLists.txt new file mode 100644 index 00000000..2d8881a8 --- /dev/null +++ b/testing/test/no_add-with-cpp-handler-from-docs/CMakeLists.txt @@ -0,0 +1,32 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CXX CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +find_package(CUDAToolkit REQUIRED) +add_executable(verify_docs main.cpp) +target_compile_features(verify_docs PRIVATE cxx_std_17) + +target_include_directories(verify_docs PRIVATE "${rapids-cmake-dir}/../docs/cpp_code_snippets/") +target_link_libraries(verify_docs PRIVATE CUDA::cudart) + +enable_testing() +add_test(NAME simple_test COMMAND verify_docs) +rapids_test_gpu_requirements(simple_test GPUS 1 PERCENT 25) diff --git a/testing/test/no_add-with-cpp-handler-from-docs/main.cpp b/testing/test/no_add-with-cpp-handler-from-docs/main.cpp new file mode 100644 index 00000000..5ef2a496 --- /dev/null +++ b/testing/test/no_add-with-cpp-handler-from-docs/main.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "rapids_cmake_ctest_allocation.cpp" +#include "rapids_cmake_ctest_allocation.hpp" + +int main() +{ + // Verify we only have a single GPU visible to us + auto allocs = rapids_cmake::full_allocation(); + + if (allocs.size() != 1) { return 1; } + + auto alloc = allocs[0]; + if (alloc.slots != 25) { return 1; } + + return 0; +} diff --git a/testing/test/no_add-with-no-resource-spec/CMakeLists.txt b/testing/test/no_add-with-no-resource-spec/CMakeLists.txt new file mode 100644 index 00000000..3e55cfed --- /dev/null +++ b/testing/test/no_add-with-no-resource-spec/CMakeLists.txt @@ -0,0 +1,39 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA CXX) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +set(CTEST_RESOURCE_SPEC_FILE "fake-value-to-stop-generation") +rapids_test_init() +unset(CTEST_RESOURCE_SPEC_FILE) + +find_package(CUDAToolkit REQUIRED) +add_executable(verify_no_alloc main.cpp) +target_compile_features(verify_no_alloc PRIVATE cxx_std_17) + +target_include_directories(verify_no_alloc PRIVATE "${rapids-cmake-dir}/../docs/cpp_code_snippets/") +target_link_libraries(verify_no_alloc PRIVATE CUDA::cudart) + +enable_testing() +add_test(NAME simple_test COMMAND verify_no_alloc) +rapids_test_gpu_requirements(simple_test GPUS 1) + +# Validate that the test runs correctly +set_tests_properties(simple_test + PROPERTIES PASS_REGULAR_EXPRESSION "failed to have a resource file" + ) diff --git a/testing/test/no_add-with-no-resource-spec/main.cpp b/testing/test/no_add-with-no-resource-spec/main.cpp new file mode 100644 index 00000000..3db17034 --- /dev/null +++ b/testing/test/no_add-with-no-resource-spec/main.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "rapids_cmake_ctest_allocation.cpp" +#include "rapids_cmake_ctest_allocation.hpp" + +int main() +{ + if (!rapids_cmake::using_resources()) { + std::cout << "failed to have a resource file" << std::endl; + return 0; + } + return 1; +} diff --git a/testing/test/rapids-test.cmake b/testing/test/rapids-test.cmake new file mode 100644 index 00000000..02fd0a87 --- /dev/null +++ b/testing/test/rapids-test.cmake @@ -0,0 +1,16 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include(${rapids-cmake-dir}/rapids-test.cmake) diff --git a/testing/utils/cmake_ctest_test.cmake b/testing/utils/cmake_ctest_test.cmake new file mode 100644 index 00000000..064c07d6 --- /dev/null +++ b/testing/utils/cmake_ctest_test.cmake @@ -0,0 +1,22 @@ +#============================================================================= +# Copyright (c) 2021-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +include_guard(GLOBAL) + +include(utils/cmake_test.cmake) + +function(add_cmake_ctest_test source_or_dir) + add_cmake_test(TEST "${source_or_dir}" ${ARGN}) +endfunction() diff --git a/testing/utils/cmake_test.cmake b/testing/utils/cmake_test.cmake index 81156f71..6d6b1d0d 100644 --- a/testing/utils/cmake_test.cmake +++ b/testing/utils/cmake_test.cmake @@ -1,5 +1,5 @@ #============================================================================= -# Copyright (c) 2021, NVIDIA CORPORATION. +# Copyright (c) 2021-2023, NVIDIA CORPORATION. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ adds a test for each generator: .. code-block:: cmake - add_cmake_build_test( (config|build|run|install) + add_cmake_build_test( (config|build|test|install) [SHOULD_FAIL ] ) @@ -42,11 +42,16 @@ adds a test for each generator: step. Expects the test to raise an error to mark failures ``build`` - Generate and build a CMake project. The CMake config and generate + Generate and build a CMake project. The CMake configuration step is constructed as a setup fixture. Expects the test to either raise an error during config, or fail to build to mark failures +``test`` + Generate, build, and ctest a CMake project. The CMake config, and + build steps are constructed as a setup fixture. + Expects the underlying ctest execution to fail to mark failures + ``install`` - Not implemented @@ -93,6 +98,7 @@ function(add_cmake_test mode source_or_dir) ${extra_configure_flags} -Drapids-cmake-testing-dir=${PROJECT_SOURCE_DIR} -Drapids-cmake-dir=${PROJECT_SOURCE_DIR}/../rapids-cmake) + elseif(mode STREQUAL "build") add_test(NAME ${test_name}_configure COMMAND ${CMAKE_COMMAND} @@ -103,10 +109,31 @@ function(add_cmake_test mode source_or_dir) -Drapids-cmake-dir=${PROJECT_SOURCE_DIR}/../rapids-cmake) add_test(NAME ${test_name} + COMMAND ${CMAKE_COMMAND} + --build ${build_dir} -j3000 ) + + set_tests_properties(${test_name}_configure PROPERTIES FIXTURES_SETUP ${test_name}) + set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${test_name}) + elseif(mode STREQUAL "test") + add_test(NAME ${test_name}_configure + COMMAND ${CMAKE_COMMAND} + -S ${src_dir} -B ${build_dir} + -G "${generator}" + ${extra_configure_flags} + -Drapids-cmake-testing-dir=${PROJECT_SOURCE_DIR} + -Drapids-cmake-dir=${PROJECT_SOURCE_DIR}/../rapids-cmake) + + add_test(NAME ${test_name}_build COMMAND ${CMAKE_COMMAND} --build ${build_dir} -j3 ) + set_tests_properties(${test_name}_build PROPERTIES DEPENDS ${test_name}_configure) + + add_test(NAME ${test_name} + COMMAND ${CMAKE_CTEST_COMMAND} -C Debug -j400 -VV + WORKING_DIRECTORY ${build_dir}) set_tests_properties(${test_name}_configure PROPERTIES FIXTURES_SETUP ${test_name}) + set_tests_properties(${test_name}_build PROPERTIES FIXTURES_SETUP ${test_name}) set_tests_properties(${test_name} PROPERTIES FIXTURES_REQUIRED ${test_name}) elseif(mode STREQUAL "install") message(FATAL_ERROR "install mode not yet implemented by add_cmake_build_test") diff --git a/testing/utils/determine_gpu_count.cmake b/testing/utils/determine_gpu_count.cmake new file mode 100644 index 00000000..78035b76 --- /dev/null +++ b/testing/utils/determine_gpu_count.cmake @@ -0,0 +1,25 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= + +function(determine_gpu_count ) + #run nvidia-smi and extract gpu details + execute_process(COMMAND nvidia-smi --list-gpus OUTPUT_VARIABLE smi_output) + + string(REPLACE "\n" ";" smi_output "${smi_output}") + list(POP_BACK smi_output) #remove the trailing `;` entry + list(LENGTH smi_output gpu_count) + set(RAPIDS_CMAKE_TESTING_GPU_COUNT ${gpu_count} PARENT_SCOPE) +endfunction() From 4768e3a26d991c609ed6f1d8d6ceb776f1df5809 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Mon, 27 Feb 2023 13:36:51 -0500 Subject: [PATCH 02/14] Provide some rapids_test_install_relocatable docs --- rapids-cmake/test/install_relocatable.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rapids-cmake/test/install_relocatable.cmake b/rapids-cmake/test/install_relocatable.cmake index 7b024b4e..15723b9d 100644 --- a/rapids-cmake/test/install_relocatable.cmake +++ b/rapids-cmake/test/install_relocatable.cmake @@ -30,7 +30,11 @@ by `ctest` in parallel with GPU awareness. DESTINATION [EXCLUDE_FROM_ALL]) -Add ... +Will install all tests created by :cmake:command:`rapids_test_add` that are +part of the provided ``INSTALL_COMPONENT_SET``. + +The :cmake:command:`rapids_test_install_relocatable` presumes that all +arguments provided to the tests are machine independent ( no absolute paths ). ``INSTALL_COMPONENT_SET`` Record which test component infrastructure to be installed From a6304ee0e5736375c19fafaf6b8337a891b57f07 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 11:02:53 -0500 Subject: [PATCH 03/14] Properly propagate runtime exceptions as failure --- rapids-cmake/test/detail/run_gpu_test.cmake | 3 +- testing/test/CMakeLists.txt | 1 + .../CMakeLists.txt | 29 +++++++++++++++++++ .../main.cu | 26 +++++++++++++++++ 4 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 testing/test/add-allocation-throws-runtime-error/CMakeLists.txt create mode 100644 testing/test/add-allocation-throws-runtime-error/main.cu diff --git a/rapids-cmake/test/detail/run_gpu_test.cmake b/rapids-cmake/test/detail/run_gpu_test.cmake index 1cd11d93..bc94c594 100644 --- a/rapids-cmake/test/detail/run_gpu_test.cmake +++ b/rapids-cmake/test/detail/run_gpu_test.cmake @@ -30,4 +30,5 @@ if(DEFINED ENV{CTEST_RESOURCE_GROUP_COUNT}) endif() endforeach() endif() -execute_process(COMMAND ${command_to_run} ${command_args} COMMAND_ECHO STDOUT) +execute_process(COMMAND ${command_to_run} ${command_args} COMMAND_ECHO STDOUT + COMMAND_ERROR_IS_FATAL ANY) diff --git a/testing/test/CMakeLists.txt b/testing/test/CMakeLists.txt index dd0c4444..3468a5a5 100644 --- a/testing/test/CMakeLists.txt +++ b/testing/test/CMakeLists.txt @@ -48,6 +48,7 @@ add_cmake_config_test(add-with-install-component.cmake) add_cmake_config_test(add-with-no-gpus.cmake) if(RAPIDS_CMAKE_TESTING_GPU_COUNT GREATER 0) add_cmake_ctest_test(add-allocation-simple) + add_cmake_ctest_test(add-allocation-throws-runtime-error) add_cmake_ctest_test(add-multi-allocations-same-gpu) add_cmake_ctest_test(add-multi-jobs-single-gpu) add_cmake_ctest_test(no_add-with-cpp-handler-from-docs) diff --git a/testing/test/add-allocation-throws-runtime-error/CMakeLists.txt b/testing/test/add-allocation-throws-runtime-error/CMakeLists.txt new file mode 100644 index 00000000..f037ff14 --- /dev/null +++ b/testing/test/add-allocation-throws-runtime-error/CMakeLists.txt @@ -0,0 +1,29 @@ +#============================================================================= +# Copyright (c) 2022-2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +cmake_minimum_required(VERSION 3.20) +project(rapids-test-project LANGUAGES CUDA) + +include(${rapids-cmake-dir}/rapids-test.cmake) + +rapids_test_init() + +add_executable(verify_alloc main.cu) + +enable_testing() +rapids_test_add(NAME simple_test COMMAND verify_alloc GPUS 1) + +# Validate that the test fails +set_tests_properties(simple_test PROPERTIES WILL_FAIL ON) diff --git a/testing/test/add-allocation-throws-runtime-error/main.cu b/testing/test/add-allocation-throws-runtime-error/main.cu new file mode 100644 index 00000000..81452fe3 --- /dev/null +++ b/testing/test/add-allocation-throws-runtime-error/main.cu @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022-2023, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +int main() +{ + throw std::bad_alloc(); + return 0; +} From 642abb37d7aecfc926967251f15169c25513c211 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 11:25:55 -0500 Subject: [PATCH 04/14] Remove changes to dependencies.yaml --- dependencies.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/dependencies.yaml b/dependencies.yaml index c6139e25..1e72f2a3 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -41,28 +41,23 @@ dependencies: packages: - cudatoolkit=11.2 - gcc<11.0.0 - - sysroot_linux-64==2.17 - matrix: cuda: "11.4" packages: - cudatoolkit=11.4 - gcc<11.0.0 - - sysroot_linux-64==2.17 - matrix: cuda: "11.5" packages: - cudatoolkit=11.5 - - sysroot_linux-64==2.17 - matrix: cuda: "11.6" packages: - cudatoolkit=11.6 - - sysroot_linux-64==2.17 - matrix: cuda: "11.8" packages: - cudatoolkit=11.8 - - sysroot_linux-64==2.17 docs: common: - output_types: [conda] From d208854a46055461751cada1d82824d506c4c38e Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 12:06:23 -0500 Subject: [PATCH 05/14] Revert "Remove changes to dependencies.yaml" This reverts commit 642abb37d7aecfc926967251f15169c25513c211. --- dependencies.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dependencies.yaml b/dependencies.yaml index 1e72f2a3..c6139e25 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -41,23 +41,28 @@ dependencies: packages: - cudatoolkit=11.2 - gcc<11.0.0 + - sysroot_linux-64==2.17 - matrix: cuda: "11.4" packages: - cudatoolkit=11.4 - gcc<11.0.0 + - sysroot_linux-64==2.17 - matrix: cuda: "11.5" packages: - cudatoolkit=11.5 + - sysroot_linux-64==2.17 - matrix: cuda: "11.6" packages: - cudatoolkit=11.6 + - sysroot_linux-64==2.17 - matrix: cuda: "11.8" packages: - cudatoolkit=11.8 + - sysroot_linux-64==2.17 docs: common: - output_types: [conda] From 50fee4559c95a28185ee618d66a53116c91efe2b Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 12:07:04 -0500 Subject: [PATCH 06/14] Updated readme as requested in code review --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c7ab70fd..4bb38ed9 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ The `rapids_test` functions simplify CTest resource allocation, allowing for tests to run in parallel without overallocating GPU resources. The most commonly used functions are: -- `rapids_test_add(NAME GPUS )` State how many GPU resources a single +- `rapids_test_add(NAME GPUS PERCENT )`: State how many GPU resources a single test requires From 2781c11d28c2b47d718f3c6860ab240b67b95b67 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 12:51:47 -0500 Subject: [PATCH 07/14] rapids-cmake/rapids-test.cmake includes generate_resource_spec --- rapids-cmake/rapids-test.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/rapids-cmake/rapids-test.cmake b/rapids-cmake/rapids-test.cmake index 2edbff26..af44780d 100644 --- a/rapids-cmake/rapids-test.cmake +++ b/rapids-cmake/rapids-test.cmake @@ -17,5 +17,6 @@ include_guard(GLOBAL) include(${CMAKE_CURRENT_LIST_DIR}/test/init.cmake) include(${CMAKE_CURRENT_LIST_DIR}/test/add.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/test/generate_resource_spec.cmake) include(${CMAKE_CURRENT_LIST_DIR}/test/gpu_requirements.cmake) include(${CMAKE_CURRENT_LIST_DIR}/test/install_relocatable.cmake) From 52dca1563cd15aecb96b786fb3827062dfd12e10 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 13:54:29 -0500 Subject: [PATCH 08/14] More style changes found during code review --- rapids-cmake/test/add.cmake | 13 +++++++------ rapids-cmake/test/detail/generate_resource_spec.cpp | 5 +++-- rapids-cmake/test/detail/record_install.cmake | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/rapids-cmake/test/add.cmake b/rapids-cmake/test/add.cmake index 607f3280..c6a85148 100644 --- a/rapids-cmake/test/add.cmake +++ b/rapids-cmake/test/add.cmake @@ -40,8 +40,8 @@ CTest with high parallel levels will cause multiple tests to run on the same GPU and quickly exhaust all memory. ``COMMAND`` - Specify the test command-line. If specifies an executable target - (created by add_executable()) it will automatically be replaced by the location of the + Specify the test command-line including any arguments. If the first argument provided is an executable + target (created by add_executable()) it will automatically be replaced by the location of the executable created at build time. ``GPUS`` @@ -95,12 +95,13 @@ function(rapids_test_add) endif() # Provide a copy of the test runner in the binary directory so that tests still can be executed if - # for some reason rapids-cmake src has been removed. - set(_rapids_run_gpu_test_script "${PROJECT_BINARY_DIR}/rapids-cmake/run_gpu_test.cmake") + # for some reason rapids-cmake src has been removed. set(_rapids_run_gpu_test_script + # "${PROJECT_BINARY_DIR}/rapids-cmake/run_gpu_test.cmake") + set(_rapids_run_gpu_test_script_dir "${PROJECT_BINARY_DIR}/rapids-cmake/") set(_rapids_run_gpu_test_script_for_install "./run_gpu_test.cmake") - if(NOT EXISTS "${_rapids_run_gpu_test_script}") + if(NOT EXISTS "${_rapids_run_gpu_test_script_dir}${_rapids_run_gpu_test_script}") file(COPY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake" - DESTINATION "${PROJECT_BINARY_DIR}/rapids-cmake/") + DESTINATION "${_rapids_run_gpu_test_script_dir}") endif() add_test(NAME ${_RAPIDS_TEST_NAME} diff --git a/rapids-cmake/test/detail/generate_resource_spec.cpp b/rapids-cmake/test/detail/generate_resource_spec.cpp index 3c1dcf57..7ae97efc 100644 --- a/rapids-cmake/test/detail/generate_resource_spec.cpp +++ b/rapids-cmake/test/detail/generate_resource_spec.cpp @@ -51,7 +51,8 @@ struct local { std::vector gpus; }; -// A hard-coded JSON printer, but it gets the job done +// A hard-coded JSON printer that generates a ctest resource-specification file: +// https://cmake.org/cmake/help/latest/manual/ctest.1.html#resource-specification-file void to_json(std::ostream& buffer, version const& v) { buffer << "\"version\": {\"major\": " << v.major << ", \"minor\": " << v.minor << "}"; @@ -73,7 +74,7 @@ void to_json(std::ostream& buffer, local const& l) buffer << "}]\n"; } -int main(int, char**) +int main() { version v{1, 0}; local l; diff --git a/rapids-cmake/test/detail/record_install.cmake b/rapids-cmake/test/detail/record_install.cmake index 9e8216b4..68553713 100644 --- a/rapids-cmake/test/detail/record_install.cmake +++ b/rapids-cmake/test/detail/record_install.cmake @@ -38,6 +38,6 @@ function(rapids_test_record_install) cmake_parse_arguments(_RAPIDS_TEST "${options}" "${one_value}" "${multi_value}" ${ARGN}) set(component ${_RAPIDS_TEST_COMPONENT}) - set_property(TARGET rapids_test_install_${component} APPEND PROPERTY "TARGETS_TO_INSTALL" + set_property(TARGET rapids_test_install_${component} APPEND PROPERTY TARGETS_TO_INSTALL "${_RAPIDS_TEST_TARGET}") endfunction() From 8c79f173a49c1450ce91d03c7a08b8d221f99880 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 14:01:13 -0500 Subject: [PATCH 09/14] remove unneeded extraction of percent value from CTEST_RESOURCE_GROUP_COUNT --- rapids-cmake/test/detail/run_gpu_test.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rapids-cmake/test/detail/run_gpu_test.cmake b/rapids-cmake/test/detail/run_gpu_test.cmake index bc94c594..b34e1d6b 100644 --- a/rapids-cmake/test/detail/run_gpu_test.cmake +++ b/rapids-cmake/test/detail/run_gpu_test.cmake @@ -25,7 +25,8 @@ if(DEFINED ENV{CTEST_RESOURCE_GROUP_COUNT}) string(REPLACE "id:" "" allocation "${allocation}") string(REPLACE ",slots:" ";" allocation "${allocation}") list(GET allocation 0 device_ids) - list(GET allocation 1 percent) + # slots are the cmake test requirements term for what we call percent. So we can ignore the + # second item in the list set(ENV{CUDA_VISIBLE_DEVICES} ${device_ids}) endif() endforeach() From cfaffb396424ce2d2002b563b95c1474454c79ca Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 14:06:11 -0500 Subject: [PATCH 10/14] remove unneeded spaces around brackets --- rapids-cmake/test/install_relocatable.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rapids-cmake/test/install_relocatable.cmake b/rapids-cmake/test/install_relocatable.cmake index 15723b9d..674b4958 100644 --- a/rapids-cmake/test/install_relocatable.cmake +++ b/rapids-cmake/test/install_relocatable.cmake @@ -34,7 +34,7 @@ Will install all tests created by :cmake:command:`rapids_test_add` that are part of the provided ``INSTALL_COMPONENT_SET``. The :cmake:command:`rapids_test_install_relocatable` presumes that all -arguments provided to the tests are machine independent ( no absolute paths ). +arguments provided to the tests are machine independent (no absolute paths). ``INSTALL_COMPONENT_SET`` Record which test component infrastructure to be installed From cbf8d90acff364dbc0a56200c009a6f63861e5f5 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 28 Feb 2023 15:50:26 -0500 Subject: [PATCH 11/14] Correct ci test failures --- rapids-cmake/test/add.cmake | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/rapids-cmake/test/add.cmake b/rapids-cmake/test/add.cmake index c6a85148..450a7d98 100644 --- a/rapids-cmake/test/add.cmake +++ b/rapids-cmake/test/add.cmake @@ -98,7 +98,7 @@ function(rapids_test_add) # for some reason rapids-cmake src has been removed. set(_rapids_run_gpu_test_script # "${PROJECT_BINARY_DIR}/rapids-cmake/run_gpu_test.cmake") set(_rapids_run_gpu_test_script_dir "${PROJECT_BINARY_DIR}/rapids-cmake/") - set(_rapids_run_gpu_test_script_for_install "./run_gpu_test.cmake") + set(_rapids_run_gpu_test_script "./run_gpu_test.cmake") if(NOT EXISTS "${_rapids_run_gpu_test_script_dir}${_rapids_run_gpu_test_script}") file(COPY "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake" DESTINATION "${_rapids_run_gpu_test_script_dir}") @@ -106,7 +106,7 @@ function(rapids_test_add) add_test(NAME ${_RAPIDS_TEST_NAME} COMMAND ${CMAKE_COMMAND} "-Dcommand_to_run=${command}" "-Dcommand_args=${args}" -P - "${_rapids_run_gpu_test_script}" + "${_rapids_run_gpu_test_script_dir}${_rapids_run_gpu_test_script}" WORKING_DIRECTORY "${_RAPIDS_TEST_WORKING_DIRECTORY}") include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/gpu_requirements.cmake) @@ -138,13 +138,8 @@ function(rapids_test_add) endif() rapids_test_record_test_component(NAME ${_RAPIDS_TEST_NAME} COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET}) - rapids_test_record_test_command(NAME - ${_RAPIDS_TEST_NAME} - COMMAND - cmake + rapids_test_record_test_command(NAME ${_RAPIDS_TEST_NAME} COMMAND cmake "-Dcommand_to_run=${command_for_install}" - "-Dcommand_args=${args}" - -P - "${_rapids_run_gpu_test_script_for_install}") + "-Dcommand_args=${args}" -P "${_rapids_run_gpu_test_script}") endif() endfunction() From b1fe07d411f589b421c9c1a22491070512712363 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 1 Mar 2023 13:42:51 -0500 Subject: [PATCH 12/14] refactor generated file names to a common location --- rapids-cmake/test/detail/default_names.cmake | 20 +++++++++++++++++++ .../test/generate_resource_spec.cmake | 3 ++- rapids-cmake/test/init.cmake | 7 +++++-- rapids-cmake/test/install_relocatable.cmake | 13 ++++++------ 4 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 rapids-cmake/test/detail/default_names.cmake diff --git a/rapids-cmake/test/detail/default_names.cmake b/rapids-cmake/test/detail/default_names.cmake new file mode 100644 index 00000000..8463af3b --- /dev/null +++ b/rapids-cmake/test/detail/default_names.cmake @@ -0,0 +1,20 @@ +#============================================================================= +# Copyright (c) 2023, NVIDIA CORPORATION. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#============================================================================= +# can't have an include guard on this file +# that breaks its usage by test/init and test/install_relocatable + +set(rapids_test_generate_exe_name generate_ctest_json) +set(rapids_test_json_file_name resource_spec.json) diff --git a/rapids-cmake/test/generate_resource_spec.cmake b/rapids-cmake/test/generate_resource_spec.cmake index 6f883888..ea7f0b34 100644 --- a/rapids-cmake/test/generate_resource_spec.cmake +++ b/rapids-cmake/test/generate_resource_spec.cmake @@ -61,8 +61,9 @@ function(rapids_test_generate_resource_spec DESTINATION filepath) } ]=]) + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/default_names.cmake) set(eval_file ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/generate_resource_spec.cpp) - set(eval_exe ${PROJECT_BINARY_DIR}/rapids-cmake/generate_ctest_json) + set(eval_exe ${PROJECT_BINARY_DIR}/rapids-cmake/${rapids_test_generate_exe_name}) set(error_file ${PROJECT_BINARY_DIR}/rapids-cmake/detect_gpus.stderr.log) if(NOT EXISTS "${eval_exe}") diff --git a/rapids-cmake/test/init.cmake b/rapids-cmake/test/init.cmake index cb0df2c6..15d27afe 100644 --- a/rapids-cmake/test/init.cmake +++ b/rapids-cmake/test/init.cmake @@ -54,11 +54,14 @@ Result Variables function(rapids_test_init) list(APPEND CMAKE_MESSAGE_CONTEXT "rapids.test.init") + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/default_names.cmake) include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/generate_resource_spec.cmake) - rapids_test_generate_resource_spec(DESTINATION "${PROJECT_BINARY_DIR}/resource_spec.json") + set(rapids_test_spec_file "${PROJECT_BINARY_DIR}/${rapids_test_json_file_name}") + + rapids_test_generate_resource_spec(DESTINATION "${rapids_test_spec_file}") if(NOT CTEST_RESOURCE_SPEC_FILE) - set(CTEST_RESOURCE_SPEC_FILE "${PROJECT_BINARY_DIR}/resource_spec.json" PARENT_SCOPE) + set(CTEST_RESOURCE_SPEC_FILE "${rapids_test_spec_file}" PARENT_SCOPE) endif() endfunction() diff --git a/rapids-cmake/test/install_relocatable.cmake b/rapids-cmake/test/install_relocatable.cmake index 674b4958..ed174d08 100644 --- a/rapids-cmake/test/install_relocatable.cmake +++ b/rapids-cmake/test/install_relocatable.cmake @@ -70,12 +70,13 @@ function(rapids_test_install_relocatable) get_target_property(targets_to_install rapids_test_install_${component} TARGETS_TO_INSTALL) get_target_property(tests_to_run rapids_test_install_${component} TESTS_TO_RUN) + include(${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/default_names.cmake) set(content - [==[ - set(CTEST_SCRIPT_DIRECTORY ".") - set(CTEST_RESOURCE_SPEC_FILE "./resource_spec.json") - execute_process(COMMAND ./generate_ctest_json OUTPUT_FILE "${CTEST_RESOURCE_SPEC_FILE}") - ]==]) + " + set(CTEST_SCRIPT_DIRECTORY \".\") + set(CTEST_RESOURCE_SPEC_FILE \"./${rapids_test_json_file_name}\") + execute_process(COMMAND ./${rapids_test_generate_exe_name} OUTPUT_FILE \"${CTEST_RESOURCE_SPEC_FILE}\") + ") foreach(test IN LISTS tests_to_run) get_test_property(${test} INSTALL_COMMAND command) @@ -103,7 +104,7 @@ function(rapids_test_install_relocatable) # We need to install the rapids-test gpu detector, and the json script we also need to write out / # install the new CTestTestfile.cmake - install(PROGRAMS "${PROJECT_BINARY_DIR}/rapids-cmake/generate_ctest_json" + install(PROGRAMS "${PROJECT_BINARY_DIR}/rapids-cmake/${rapids_test_generate_exe_name}" COMPONENT ${_RAPIDS_TEST_INSTALL_COMPONENT_SET} DESTINATION ${_RAPIDS_TEST_DESTINATION} ${to_exclude}) install(FILES "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/detail/run_gpu_test.cmake" From d317e425b917072845bce61e74f32dd082bde338 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Wed, 1 Mar 2023 16:24:36 -0500 Subject: [PATCH 13/14] simplify generate_resource_spec.cpp --- .../test/detail/generate_resource_spec.cpp | 55 ++++++++----------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/rapids-cmake/test/detail/generate_resource_spec.cpp b/rapids-cmake/test/detail/generate_resource_spec.cpp index 7ae97efc..8ca335d5 100644 --- a/rapids-cmake/test/detail/generate_resource_spec.cpp +++ b/rapids-cmake/test/detail/generate_resource_spec.cpp @@ -33,24 +33,6 @@ struct gpu { int slots = 0; }; -struct local { - local() - { - int nDevices = 0; - cudaGetDeviceCount(&nDevices); - if (nDevices == 0) { - gpus.emplace_back(0); - } else { - for (int i = 0; i < nDevices; ++i) { - cudaDeviceProp prop; - cudaGetDeviceProperties(&prop, i); - gpus.emplace_back(i, prop); - } - } - } - std::vector gpus; -}; - // A hard-coded JSON printer that generates a ctest resource-specification file: // https://cmake.org/cmake/help/latest/manual/ctest.1.html#resource-specification-file void to_json(std::ostream& buffer, version const& v) @@ -61,28 +43,35 @@ void to_json(std::ostream& buffer, gpu const& g) { buffer << "\t\t{\"id\": \"" << g.id << "\", \"slots\": " << g.slots << "}"; } -void to_json(std::ostream& buffer, local const& l) -{ - buffer << "\"local\": [{\n"; - buffer << "\t\"gpus\": [\n"; - for (int i = 0; i < l.gpus.size(); ++i) { - to_json(buffer, l.gpus[i]); - if (i != (l.gpus.size() - 1)) { buffer << ","; } - buffer << "\n"; - } - buffer << "\t]\n"; - buffer << "}]\n"; -} int main() { - version v{1, 0}; - local l; + std::vector gpus; + int nDevices = 0; + cudaGetDeviceCount(&nDevices); + if (nDevices == 0) { + gpus.emplace_back(0); + } else { + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaGetDeviceProperties(&prop, i); + gpus.emplace_back(i, prop); + } + } + version v{1, 0}; std::cout << "{\n"; to_json(std::cout, v); std::cout << ",\n"; - to_json(std::cout, l); + std::cout << "\"local\": [{\n"; + std::cout << "\t\"gpus\": [\n"; + for (int i = 0; i < gpus.size(); ++i) { + to_json(std::cout, gpus[i]); + if (i != (gpus.size() - 1)) { std::cout << ","; } + std::cout << "\n"; + } + std::cout << "\t]\n"; + std::cout << "}]\n"; std::cout << "}" << std::endl; return 0; } From e6a84036b3ae2d132aa144b41bc8d526c956130f Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Tue, 7 Mar 2023 10:13:55 -0500 Subject: [PATCH 14/14] Update rapids-cmake/test/add.cmake Co-authored-by: Vyas Ramasubramani --- rapids-cmake/test/add.cmake | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rapids-cmake/test/add.cmake b/rapids-cmake/test/add.cmake index 450a7d98..a7817468 100644 --- a/rapids-cmake/test/add.cmake +++ b/rapids-cmake/test/add.cmake @@ -95,8 +95,7 @@ function(rapids_test_add) endif() # Provide a copy of the test runner in the binary directory so that tests still can be executed if - # for some reason rapids-cmake src has been removed. set(_rapids_run_gpu_test_script - # "${PROJECT_BINARY_DIR}/rapids-cmake/run_gpu_test.cmake") + # for some reason rapids-cmake src has been removed. set(_rapids_run_gpu_test_script_dir "${PROJECT_BINARY_DIR}/rapids-cmake/") set(_rapids_run_gpu_test_script "./run_gpu_test.cmake") if(NOT EXISTS "${_rapids_run_gpu_test_script_dir}${_rapids_run_gpu_test_script}")