mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.4 samples update - v13.4-public
Release 13.4 of the CUDA Samples supported by CUDA Toolkit 13.4. See Changelog for more information.
This commit is contained in:
31
cpp/3_CUDA_Features/localityDomains/CMakeLists.txt
Normal file
31
cpp/3_CUDA_Features/localityDomains/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/Modules")
|
||||
|
||||
project(localityDomains LANGUAGES C CXX CUDA)
|
||||
|
||||
find_package(CUDAToolkit REQUIRED)
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_CUDA_ARCHITECTURES 75 80 86 87 89 90 100 110 120)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Wno-deprecated-gpu-targets")
|
||||
if(ENABLE_CUDA_DEBUG)
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -G") # enable cuda-gdb (may significantly affect performance on some targets)
|
||||
else()
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -lineinfo") # add line information to all builds for debug tools (exclusive to -G option)
|
||||
endif()
|
||||
|
||||
# Source file
|
||||
# Add target for localityDomains
|
||||
add_executable(localityDomains localityDomains.cu)
|
||||
|
||||
target_compile_options(localityDomains PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)
|
||||
|
||||
target_compile_features(localityDomains PRIVATE cxx_std_17 cuda_std_17)
|
||||
|
||||
set_target_properties(localityDomains PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
|
||||
# Include installation configuration
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/InstallSamples.cmake)
|
||||
setup_samples_install()
|
||||
86
cpp/3_CUDA_Features/localityDomains/README.md
Normal file
86
cpp/3_CUDA_Features/localityDomains/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# localityDomains - CUDA Runtime API Locality Domains
|
||||
|
||||
## Description
|
||||
|
||||
This CUDA Runtime API sample demonstrates localized compute and memory resources.
|
||||
|
||||
Compute is localized by splitting a device's SM resources into locality domain partitions and constructing a green context and stream per locality domain. Memory is localized by allocating from localized memory pools.
|
||||
|
||||
## What You'll Learn
|
||||
How to:
|
||||
- query a device's locality domain count and SM count per domain
|
||||
- partition SM resources by locality domain ID
|
||||
- create green contexts and streams from localized SM partitions
|
||||
- create localized memory pools and allocate from them asynchronously
|
||||
- query the locality domain associated with a stream and device pointer
|
||||
|
||||
## Key Concepts
|
||||
|
||||
- **Locality domain** — a portion of a GPU that contains streaming multiprocessors (SMs) and device memory.
|
||||
**Green context** — an execution context created from a selected subset of device resources.
|
||||
- **Localized memory pool** — a stream-ordered allocator whose physical memory is placed in a selected locality domain.
|
||||
|
||||
## Key APIs
|
||||
|
||||
### CUDA Runtime
|
||||
|
||||
- `cudaDeviceGetAttribute` — query the number of locality domains and SMs per domain
|
||||
- `cudaDevSmResourceSplit` — partition the device's SM resources
|
||||
- `cudaMemPoolCreate` — create a localized memory pool and allocate from it
|
||||
- `cudaStreamGetDevResource` — inspect stream locality
|
||||
- `cudaPointerGetAttributes` — inspect allocation locality
|
||||
|
||||
## Requirements
|
||||
|
||||
### Hardware
|
||||
|
||||
- NVIDIA GPU that supports locality domains and stream-ordered memory pools
|
||||
|
||||
### Software
|
||||
|
||||
- CUDA Toolkit and NVIDIA driver with locality domain support
|
||||
- Linux or QNX on x86_64 or aarch64
|
||||
- CMake 3.20 or newer
|
||||
- A C++17-capable host compiler
|
||||
|
||||
## How to Build
|
||||
|
||||
See the [top-level README](../../../README.md#building-cuda-samples) for full build instructions, including how to build all samples or a single sample standalone.
|
||||
|
||||
## How to Run
|
||||
|
||||
```bash
|
||||
./localityDomains
|
||||
```
|
||||
|
||||
No command-line arguments are required. The sample always runs on device 0.
|
||||
|
||||
## Expected Output
|
||||
|
||||
The number of locality domains and SMs depends on the GPU. A run has the following form:
|
||||
|
||||
```text
|
||||
CUDA Runtime API locality domains sample
|
||||
Locality domain count: <domain count>
|
||||
SMs per locality domain: <SM count>
|
||||
Device SMs split into <domain count> partitions
|
||||
- result[0]: .localityDomainId = 0, .smCount = <SM count>
|
||||
...
|
||||
Green context stream 0 is localized to locality domain 0
|
||||
...
|
||||
allocation 0x<address> is localized to locality domain 0
|
||||
...
|
||||
```
|
||||
|
||||
If device 0 does not support memory pools, the sample reports that it is waiving execution and exits with status EXIT_WAIVED.
|
||||
|
||||
## Files
|
||||
|
||||
- `localityDomains.cu` — Runtime API example
|
||||
- `README.md` — this file
|
||||
- `CMakeLists.txt` — build configuration
|
||||
|
||||
## See Also
|
||||
|
||||
- [CUDA Runtime API](https://docs.nvidia.com/cuda/cuda-runtime-api/)
|
||||
- [CUDA Programming Guide](https://docs.nvidia.com/cuda/cuda-programming-guide/)
|
||||
171
cpp/3_CUDA_Features/localityDomains/localityDomains.cu
Normal file
171
cpp/3_CUDA_Features/localityDomains/localityDomains.cu
Normal file
@@ -0,0 +1,171 @@
|
||||
/* Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of NVIDIA CORPORATION nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
|
||||
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This sample demonstrates CUDA locality domains using the Runtime API.
|
||||
* It creates one green context and stream per reported locality domain and
|
||||
* allocates one localized memory-pool chunk per locality domain, then queries the
|
||||
* placement back from both the stream resource and the device pointer.
|
||||
*/
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cuda_runtime.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "CUDA Runtime API locality domains sample" << std::endl;
|
||||
|
||||
int dev = 0;
|
||||
cudaSetDevice(dev);
|
||||
|
||||
int memoryPoolsSupported = 0;
|
||||
cudaDeviceGetAttribute(&memoryPoolsSupported, cudaDevAttrMemoryPoolsSupported, dev);
|
||||
|
||||
if (!memoryPoolsSupported) {
|
||||
std::cout << "Waiving execution as the device does not support memory pools." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Device information
|
||||
int localityDomainCount = 0;
|
||||
{
|
||||
int localityDomainSmCount = 0;
|
||||
cudaDeviceGetAttribute(&localityDomainCount, cudaDevAttrLocalityDomainCount, dev);
|
||||
cudaDeviceGetAttribute(&localityDomainSmCount, cudaDevAttrLocalityDomainMultiprocessorCount, dev);
|
||||
|
||||
std::cout << "Locality domain count: " << localityDomainCount << std::endl;
|
||||
std::cout << "SMs per locality domain: " << localityDomainSmCount << std::endl;
|
||||
}
|
||||
|
||||
// Construct localized green contexts and streams
|
||||
std::vector<cudaExecutionContext_t> greenContexts(localityDomainCount);
|
||||
std::vector<cudaStream_t> streams(localityDomainCount);
|
||||
{
|
||||
cudaDevResource smResource = {};
|
||||
cudaDeviceGetDevResource(dev, &smResource, cudaDevResourceTypeSm);
|
||||
|
||||
std::vector<cudaDevSmResourceGroupParams> params(localityDomainCount);
|
||||
for (size_t i = 0; i < localityDomainCount; i++) {
|
||||
std::memset(¶ms[i], 0, sizeof(params[i]));
|
||||
params[i].flags = cudaDevSmResourceGroupLocalityDomainId;
|
||||
params[i].localityDomainId = static_cast<unsigned int>(i);
|
||||
}
|
||||
|
||||
std::vector<cudaDevResource> result(localityDomainCount);
|
||||
cudaDevResource remainder = {};
|
||||
|
||||
cudaDevSmResourceSplit(result.data(), localityDomainCount, &smResource, &remainder, 0, params.data());
|
||||
std::cout << "Device SMs split into " << localityDomainCount << " partitions" << std::endl;
|
||||
for (size_t i = 0; i < localityDomainCount; i++) {
|
||||
std::cout << " - result[" << i << "]: .localityDomainId = " << result[i].sm.localityDomainId
|
||||
<< ", .smCount = " << result[i].sm.smCount << std::endl;
|
||||
}
|
||||
if (remainder.sm.smCount > 0) {
|
||||
std::cout << " - remainder: .localityDomainId = none, .smCount = " << remainder.sm.smCount << std::endl;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < localityDomainCount; i++) {
|
||||
cudaDevResourceDesc_t desc = nullptr;
|
||||
cudaDevResourceGenerateDesc(&desc, &result[i], 1);
|
||||
cudaGreenCtxCreate(&greenContexts[i], desc, dev, 0);
|
||||
cudaExecutionCtxStreamCreate(&streams[i], greenContexts[i], cudaStreamNonBlocking, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Inspect locality of streams
|
||||
{
|
||||
for (size_t i = 0; i < localityDomainCount; i++) {
|
||||
cudaDevResource streamSmResource = {};
|
||||
cudaStreamGetDevResource(streams[i], &streamSmResource, cudaDevResourceTypeSm);
|
||||
bool isStreamLocalized = (streamSmResource.sm.flags & cudaDevSmResourceGroupLocalityDomainId) != 0;
|
||||
std::cout << "Green context stream " << i << " ";
|
||||
if (isStreamLocalized) {
|
||||
unsigned int streamLocalityDomain = streamSmResource.sm.localityDomainId;
|
||||
std::cout << "is localized to locality domain " << streamLocalityDomain << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << "is not localized" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate localized memory
|
||||
size_t allocationSize = 1 << 20;
|
||||
std::vector<void *> localizedPtrs(localityDomainCount);
|
||||
std::vector<cudaMemPool_t> pools(localityDomainCount);
|
||||
{
|
||||
for (size_t i = 0; i < localityDomainCount; i++) {
|
||||
cudaMemPoolProps poolProps = {};
|
||||
poolProps.allocType = cudaMemAllocationTypePinned;
|
||||
poolProps.location.type = cudaMemLocationTypeDeviceLocalityDomain;
|
||||
poolProps.location.localized.deviceId = static_cast<unsigned char>(dev);
|
||||
poolProps.location.localized.localityDomainId = static_cast<unsigned char>(i);
|
||||
|
||||
cudaMemPoolCreate(&pools[i], &poolProps);
|
||||
cudaMallocFromPoolAsync(&localizedPtrs[i], allocationSize, pools[i], streams[i]);
|
||||
cudaStreamSynchronize(streams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Inspect locality of allocations
|
||||
{
|
||||
for (void *ptr : localizedPtrs) {
|
||||
cudaPointerAttributes pointerAttributes = {};
|
||||
cudaPointerGetAttributes(&pointerAttributes, ptr);
|
||||
|
||||
std::cout << "allocation 0x" << std::hex << reinterpret_cast<std::uintptr_t>(ptr) << std::dec;
|
||||
if (pointerAttributes.localityDomainOrdinal == -1) {
|
||||
std::cout << " is not localized." << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << " is localized to locality domain " << pointerAttributes.localityDomainOrdinal
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up
|
||||
for (size_t i = 0; i < localizedPtrs.size(); i++) {
|
||||
cudaFreeAsync(localizedPtrs[i], streams[i]);
|
||||
}
|
||||
for (cudaStream_t stream : streams) {
|
||||
cudaStreamSynchronize(stream);
|
||||
cudaStreamDestroy(stream);
|
||||
}
|
||||
for (cudaExecutionContext_t greenContext : greenContexts) {
|
||||
cudaExecutionCtxDestroy(greenContext);
|
||||
}
|
||||
for (cudaMemPool_t pool : pools) {
|
||||
cudaMemPoolDestroy(pool);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user