mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-09-12 01:06:53 +08:00
Release 13.4 of the CUDA Samples supported by CUDA Toolkit 13.4. See Changelog for more information.
145 lines
4.4 KiB
Plaintext
145 lines
4.4 KiB
Plaintext
/* 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 <cuda_runtime_api.h>
|
|
#include <memory.h>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <stdio.h>
|
|
#include <cuda/cmath>
|
|
/**
|
|
* 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<length; i++)
|
|
{
|
|
A[i] = rand() / (float)RAND_MAX;
|
|
}
|
|
}
|
|
|
|
void serialVecAdd(float* A, float* B, float* C, int length)
|
|
{
|
|
for(int i=0; i<length; i++)
|
|
{
|
|
C[i] = A[i] + B[i];
|
|
}
|
|
}
|
|
|
|
bool vectorApproximatelyEqual(float* A, float* B, int length, float epsilon=0.00001)
|
|
{
|
|
for(int i=0; i<length; i++)
|
|
{
|
|
if(fabs(A[i] -B[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<<<blocks, threads>>>(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;
|
|
}
|