/* 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. */ /** * Vector addition: C = A + B. * * This sample is a very basic sample that implements element by element * vector addition. It is the same as the sample illustrating Chapter 2 * of the programming guide with some additions like error checking. */ #include #include #include #include #include #include /** * CUDA Kernel Device code * * Computes the vector addition of A and B into C. The 3 vectors have the same * number of elements. This exmple shows Vector addition using Unified memory. */ __global__ void vecAdd(float* A, float* B, float* C, int vectorLength) { int workIndex = threadIdx.x + blockIdx.x*blockDim.x; if(workIndex < vectorLength) { C[workIndex] = A[workIndex] + B[workIndex]; } } void initArray(float* A, int length) { std::srand(std::time({})); for(int i=0; i epsilon) { printf("Index %d mismatch: %f != %f", i, A[i], B[i]); return false; } } return true; } int main(int argc, char** argv) { int vectorLength = 1024; if(argc >=2) { vectorLength = std::atoi(argv[1]); } //unified-memory-example-begin // Pointers to memory vectors float* A = nullptr; float* B = nullptr; float* C = nullptr; float* comparisonResult = (float*)malloc(vectorLength*sizeof(float)); // Use unified memory to allocate buffers cudaMallocManaged(&A, vectorLength*sizeof(float)); cudaMallocManaged(&B, vectorLength*sizeof(float)); cudaMallocManaged(&C, vectorLength*sizeof(float)); // Initialize vectors on the host initArray(A, vectorLength); initArray(B, vectorLength); // Launch the kernel. Unified memory will make sure A, B, and C are // accessible to the GPU int threads = 256; int blocks = cuda::ceil_div(vectorLength, threads); vecAdd<<>>(A, B, C, vectorLength); // Wait for the kernel to complete execution cudaDeviceSynchronize(); // Perform computation serially on CPU for comparison serialVecAdd(A, B, comparisonResult, vectorLength); // Confirm that CPU and GPU got the same answer if(vectorApproximatelyEqual(C, comparisonResult, vectorLength)) { printf("Unified Memory: CPU and GPU answers match\n"); } else { printf("Unified Memory: Error - CPU and GPU answers do not match\n"); } // Clean Up cudaFree(A); cudaFree(B); cudaFree(C); free(comparisonResult); //unified-memory-example-end return 0; }