Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Exclude large directories that are never needed inside the container build.
# The Containerfiles use explicit COPY commands for the three things they need:
# Common/, cmake/, and the specific sample directory.

# Git internals
.git/

# CMake build trees
build*/

# Container build trees
build-container*/

# Windows-only pre-built binaries
bin/win64/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
build
build-container
.vs
.clangd
test
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ To build samples with new CUDA Toolkit(CUDA 13.0 or later) and UMD(Version 580 o
cmake -DCMAKE_PREFIX_PATH=/usr/local/cuda/lib64/stubs/ ..
```

### Building Container Images

Individual samples can be built and run as OCI container images without a local
CUDA installation. See [container/README.md](./container/README.md) for details.

## Install Samples

### Installation Path Structure
Expand Down
32 changes: 32 additions & 0 deletions Samples/1_Utilities/deviceQuery/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
ARG CUDA_IMAGE_VERSION=12.6.0

# ---- Build stage ----
FROM nvidia/cuda:${CUDA_IMAGE_VERSION}-devel-ubuntu22.04 AS builder

RUN apt-get update && apt-get install -y --no-install-recommends \
cmake \
make \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /cuda-samples

# Copy only what is needed to build this sample.
# The directory structure must be preserved so that the relative paths in
# the sample's CMakeLists.txt (e.g. ../../../Common) resolve correctly.
COPY Common/ Common/
COPY cmake/ cmake/
COPY Samples/1_Utilities/deviceQuery/ Samples/1_Utilities/deviceQuery/

RUN cmake -S Samples/1_Utilities/deviceQuery \
-B Samples/1_Utilities/deviceQuery/build \
-DCMAKE_BUILD_TYPE=Release \
&& cmake --build Samples/1_Utilities/deviceQuery/build --parallel $(nproc)

# ---- Runtime stage ----
FROM nvidia/cuda:${CUDA_IMAGE_VERSION}-base-ubuntu22.04

COPY --from=builder \
/cuda-samples/Samples/1_Utilities/deviceQuery/build/deviceQuery \
/usr/local/bin/deviceQuery

ENTRYPOINT ["deviceQuery"]
34 changes: 34 additions & 0 deletions Samples/4_CUDA_Libraries/conjugateGradient/Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
ARG CUDA_IMAGE_VERSION=12.6.0

# ---- Build stage ----
FROM nvidia/cuda:${CUDA_IMAGE_VERSION}-devel-ubuntu22.04 AS builder

RUN apt-get update && apt-get install -y --no-install-recommends \
cmake \
make \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /cuda-samples

# Copy only what is needed to build this sample.
# The directory structure must be preserved so that the relative paths in
# the sample's CMakeLists.txt (e.g. ../../../Common) resolve correctly.
COPY Common/ Common/
COPY cmake/ cmake/
COPY Samples/4_CUDA_Libraries/conjugateGradient/ Samples/4_CUDA_Libraries/conjugateGradient/

RUN cmake -S Samples/4_CUDA_Libraries/conjugateGradient \
-B Samples/4_CUDA_Libraries/conjugateGradient/build \
-DCMAKE_BUILD_TYPE=Release \
&& cmake --build Samples/4_CUDA_Libraries/conjugateGradient/build --parallel $(nproc)

# ---- Runtime stage ----
# The 'runtime' image (vs 'base') includes the CUDA math library runtimes
# (cublas, cusparse, cufft, etc.), so no extra packages are needed here.
FROM nvidia/cuda:${CUDA_IMAGE_VERSION}-runtime-ubuntu22.04

COPY --from=builder \
/cuda-samples/Samples/4_CUDA_Libraries/conjugateGradient/build/conjugateGradient \
/usr/local/bin/conjugateGradient

ENTRYPOINT ["conjugateGradient"]
67 changes: 67 additions & 0 deletions cmake/ContainerSamples.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# ContainerSamples.cmake
#
# Provides add_container_sample() for creating container build and run targets
# for individual CUDA samples. No CUDA toolkit is required on the host; all
# compilation happens inside the container using the devel base image.
#
# Any OCI-compatible CLI (docker, podman, nerdctl, …) is supported. The tool
# is located automatically, or can be overridden by setting CONTAINER_EXECUTABLE
# before including this module.
#
# Usage (from a CUDA-free CMakeLists.txt):
#
# include(cmake/ContainerSamples.cmake)
# add_container_sample(Samples/1_Utilities/deviceQuery)
#
# This creates two targets per sample:
# container_build_<name> -- builds the image from the sample's Containerfile
# container_run_<name> -- runs the image with GPU access

find_program(CONTAINER_EXECUTABLE
NAMES docker podman nerdctl
REQUIRED
DOC "OCI-compatible container CLI used to build and run sample images"
)

# CMAKE_CURRENT_LIST_DIR is the directory of this file (cmake/), so the repo
# root is one level up regardless of where the including CMakeLists.txt lives.
set(_CUDA_SAMPLES_ROOT "${CMAKE_CURRENT_LIST_DIR}/..")

function(add_container_sample SAMPLE_REL_PATH)
get_filename_component(SAMPLE_NAME "${SAMPLE_REL_PATH}" NAME)

# Accept either 'Containerfile' (preferred) or 'Dockerfile' (legacy name).
set(_CONTAINERFILE "${_CUDA_SAMPLES_ROOT}/${SAMPLE_REL_PATH}/Containerfile")
if(NOT EXISTS "${_CONTAINERFILE}")
set(_CONTAINERFILE "${_CUDA_SAMPLES_ROOT}/${SAMPLE_REL_PATH}/Dockerfile")
endif()

if(NOT EXISTS "${_CONTAINERFILE}")
message(WARNING "add_container_sample: no Containerfile found for '${SAMPLE_NAME}' "
"(expected ${_CUDA_SAMPLES_ROOT}/${SAMPLE_REL_PATH}/Containerfile)")
return()
endif()

string(TOLOWER "${SAMPLE_NAME}" _SAMPLE_NAME_LOWER)
set(_IMAGE_TAG "cuda-samples/${_SAMPLE_NAME_LOWER}:latest")

set(_BUILD_ARGS --file "${_CONTAINERFILE}" --tag "${_IMAGE_TAG}")
if(CUDA_IMAGE_VERSION)
list(APPEND _BUILD_ARGS --build-arg "CUDA_IMAGE_VERSION=${CUDA_IMAGE_VERSION}")
endif()

add_custom_target(container_build_${SAMPLE_NAME}
COMMAND "${CONTAINER_EXECUTABLE}" build
${_BUILD_ARGS}
"${_CUDA_SAMPLES_ROOT}"
WORKING_DIRECTORY "${_CUDA_SAMPLES_ROOT}"
COMMENT "Building container image ${_IMAGE_TAG}"
VERBATIM
)

add_custom_target(container_run_${SAMPLE_NAME}
COMMAND "${CONTAINER_EXECUTABLE}" run --rm --runtime=nvidia --gpus all "${_IMAGE_TAG}"
COMMENT "Running ${_IMAGE_TAG}"
VERBATIM
)
endfunction()
24 changes: 24 additions & 0 deletions container/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.20)

# This project generates container build and run targets for individual CUDA
# samples. It does NOT require a CUDA toolkit or GPU on the host; all
# compilation happens inside the container.
#
# Configure and build from the repo root:
#
# cmake -B build-container -S container/
# cmake --build build-container --target container_build_deviceQuery

project(cuda-samples-container LANGUAGES NONE)

set(CUDA_IMAGE_VERSION "12.6.0" CACHE STRING
"CUDA image version used as the base for container builds (e.g. 12.6.2, 13.1.0)")

include(../cmake/ContainerSamples.cmake)

# ---------------------------------------------------------------------------
# Register samples that have a Containerfile / Dockerfile.
# Add further samples here as container support is extended.
# ---------------------------------------------------------------------------
add_container_sample(Samples/1_Utilities/deviceQuery)
add_container_sample(Samples/4_CUDA_Libraries/conjugateGradient)
102 changes: 102 additions & 0 deletions container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Building CUDA Samples as Container Images

Individual CUDA samples can be built and run as OCI container images. This
requires no CUDA toolkit or GPU driver on the build host — all compilation
happens inside the container using the CUDA devel base image.

## Prerequisites

- An OCI-compatible container CLI: [Docker](https://docs.docker.com/engine/install/),
[Podman](https://podman.io/docs/installation), or
[nerdctl](https://github.com/containerd/nerdctl)
- CMake 3.20 or later

## Configure

From the repository root, configure the container build project:

```bash
cmake -B build-container -S container/
```

CMake will automatically detect `docker`, `podman`, or `nerdctl` (in that
order). To use a specific tool, pass it explicitly:

```bash
cmake -B build-container -S container/ -DCONTAINER_EXECUTABLE=/usr/bin/podman
```

## Build a sample image

```bash
cmake --build build-container --target container_build_deviceQuery
cmake --build build-container --target container_build_conjugateGradient
```

Each target runs the equivalent of:

```bash
docker build \
--file Samples/<category>/<name>/Containerfile \
--tag cuda-samples/<name>:latest \
.
```

using the repo root as the build context.

## Run a sample

Running a sample requires a GPU on the current machine and the
[NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/)
installed on the host.

```bash
cmake --build build-container --target container_run_deviceQuery
```

Or directly:

```bash
docker run --rm --runtime=nvidia --gpus=all cuda-samples/devicequery:latest
```

## CUDA image version

The Containerfiles default to the version set by `CUDA_IMAGE_VERSION` in
[CMakeLists.txt](CMakeLists.txt). Override it at configure time to build
against a different CUDA base image:

```bash
cmake -B build-container -S container/ -DCUDA_IMAGE_VERSION=13.1.0
```

To tag the image to reflect the version, pass `--tag` directly:

```bash
docker build \
--build-arg CUDA_IMAGE_VERSION=13.1.0 \
--file Samples/1_Utilities/deviceQuery/Containerfile \
--tag cuda-samples/devicequery:cuda13.1.0 \
.
```

## Adding container support for a new sample

1. Add a `Containerfile` to the sample's directory (see an existing sample for
reference). The build context is always the repository root, so the
directory structure under `/cuda-samples/` inside the container must mirror
the repository layout so that relative paths in the sample's `CMakeLists.txt`
resolve correctly.

2. Register the sample in [CMakeLists.txt](CMakeLists.txt):

```cmake
add_container_sample(Samples/<category>/<name>)
```

## Samples with container support

| Sample | Category |
|--------|----------|
| [deviceQuery](../Samples/1_Utilities/deviceQuery/) | Utilities |
| [conjugateGradient](../Samples/4_CUDA_Libraries/conjugateGradient/) | CUDA Libraries |