mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-13 00:08:26 +08:00
CUDA 13.2 samples update (#432)
- Added Python samples for CUDA Python 1.0 release - Renamed top-level `Samples` directory to `cpp` to accommodate Python samples.
This commit is contained in:
18
cpp/0_Introduction/matrixMulDrv/.vscode/c_cpp_properties.json
vendored
Normal file
18
cpp/0_Introduction/matrixMulDrv/.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**",
|
||||
"${workspaceFolder}/../../../Common"
|
||||
],
|
||||
"defines": [],
|
||||
"compilerPath": "/usr/local/cuda/bin/nvcc",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "gnu++14",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"configurationProvider": "ms-vscode.makefile-tools"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
7
cpp/0_Introduction/matrixMulDrv/.vscode/extensions.json
vendored
Normal file
7
cpp/0_Introduction/matrixMulDrv/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"nvidia.nsight-vscode-edition",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.makefile-tools"
|
||||
]
|
||||
}
|
||||
72
cpp/0_Introduction/matrixMulDrv/CMakeLists.txt
Normal file
72
cpp/0_Introduction/matrixMulDrv/CMakeLists.txt
Normal file
@@ -0,0 +1,72 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/Modules")
|
||||
|
||||
project(matrixMulDrv 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()
|
||||
|
||||
# Include directories and libraries
|
||||
include_directories(../../../Common)
|
||||
|
||||
# Source file
|
||||
# Add target for matrixMulDrv
|
||||
add_executable(matrixMulDrv matrixMulDrv.cpp)
|
||||
|
||||
target_compile_options(matrixMulDrv PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>)
|
||||
|
||||
target_compile_features(matrixMulDrv PRIVATE cxx_std_17 cuda_std_17)
|
||||
|
||||
set_target_properties(matrixMulDrv PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
|
||||
|
||||
target_include_directories(matrixMulDrv PRIVATE
|
||||
${CUDAToolkit_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(matrixMulDrv PUBLIC
|
||||
CUDA::cuda_driver
|
||||
)
|
||||
|
||||
set(CUDA_FATBIN_FILE "${CMAKE_CURRENT_BINARY_DIR}/matrixMul_kernel64.fatbin")
|
||||
set(CUDA_KERNEL_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/matrixMul_kernel.cu")
|
||||
|
||||
# Construct GENCODE_FLAGS explicitly from CUDA architectures
|
||||
set(GENCODE_FLAGS "")
|
||||
foreach(arch ${CMAKE_CUDA_ARCHITECTURES})
|
||||
list(APPEND GENCODE_FLAGS "-gencode=arch=compute_${arch},code=sm_${arch}")
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "QNX")
|
||||
set(INCLUDES_LIST)
|
||||
foreach(dir ${CUDAToolkit_INCLUDE_DIRS})
|
||||
list(APPEND INCLUDES_LIST "-I${dir}")
|
||||
endforeach()
|
||||
string(JOIN " " INCLUDES "${INCLUDES_LIST}")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${CUDA_FATBIN_FILE}
|
||||
COMMAND ${CMAKE_CUDA_COMPILER} ${INCLUDES} ${ALL_CCFLAGS} -Wno-deprecated-gpu-targets ${GENCODE_FLAGS} -o ${CUDA_FATBIN_FILE} -fatbin ${CUDA_KERNEL_SOURCE}
|
||||
DEPENDS ${CUDA_KERNEL_SOURCE}
|
||||
COMMENT "Building CUDA fatbin: ${CUDA_FATBIN_FILE}"
|
||||
)
|
||||
|
||||
# Create a dummy target for fatbin generation
|
||||
add_custom_target(generate_fatbin_matmulDrv ALL DEPENDS ${CUDA_FATBIN_FILE})
|
||||
|
||||
# Ensure matrixMulDrv depends on the fatbin
|
||||
add_dependencies(matrixMulDrv generate_fatbin_matmulDrv)
|
||||
|
||||
# Include installation configuration
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/InstallSamples.cmake)
|
||||
setup_samples_install()
|
||||
32
cpp/0_Introduction/matrixMulDrv/README.md
Normal file
32
cpp/0_Introduction/matrixMulDrv/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# matrixMulDrv - Matrix Multiplication (CUDA Driver API Version)
|
||||
|
||||
## Description
|
||||
|
||||
This sample implements matrix multiplication and uses the new CUDA 4.0 kernel launch Driver API. It has been written for clarity of exposition to illustrate various CUDA programming principles, not with the goal of providing the most performant generic kernel for matrix multiplication. CUBLAS provides high-performance matrix multiplication.
|
||||
|
||||
## Key Concepts
|
||||
|
||||
CUDA Driver API, Matrix Multiply
|
||||
|
||||
## Supported SM Architectures
|
||||
|
||||
[SM 5.0 ](https://developer.nvidia.com/cuda-gpus) [SM 5.2 ](https://developer.nvidia.com/cuda-gpus) [SM 5.3 ](https://developer.nvidia.com/cuda-gpus) [SM 6.0 ](https://developer.nvidia.com/cuda-gpus) [SM 6.1 ](https://developer.nvidia.com/cuda-gpus) [SM 7.0 ](https://developer.nvidia.com/cuda-gpus) [SM 7.2 ](https://developer.nvidia.com/cuda-gpus) [SM 7.5 ](https://developer.nvidia.com/cuda-gpus) [SM 8.0 ](https://developer.nvidia.com/cuda-gpus) [SM 8.6 ](https://developer.nvidia.com/cuda-gpus) [SM 8.7 ](https://developer.nvidia.com/cuda-gpus) [SM 8.9 ](https://developer.nvidia.com/cuda-gpus) [SM 9.0 ](https://developer.nvidia.com/cuda-gpus)
|
||||
|
||||
## Supported OSes
|
||||
|
||||
Linux, Windows
|
||||
|
||||
## Supported CPU Architecture
|
||||
|
||||
x86_64, armv7l, aarch64
|
||||
|
||||
## CUDA APIs involved
|
||||
|
||||
### [CUDA Driver API](http://docs.nvidia.com/cuda/cuda-driver-api/index.html)
|
||||
cuMemcpyDtoH, cuLaunchKernel, cuMemcpyHtoD, cuDeviceGetName, cuDeviceTotalMem, cuDeviceGetAttribute, cuModuleLoadData, cuOccupancyMaxPotentialBlockSize, cuMemAlloc, cuMemFree, cuCtxDestroy, cuModuleGetFunction, cuCtxCreate
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Download and install the [CUDA Toolkit](https://developer.nvidia.com/cuda-downloads) for your corresponding platform.
|
||||
|
||||
## References (for more details)
|
||||
40
cpp/0_Introduction/matrixMulDrv/matrixMul.h
Normal file
40
cpp/0_Introduction/matrixMulDrv/matrixMul.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
#ifndef _MATRIXMUL_H_
|
||||
#define _MATRIXMUL_H_
|
||||
|
||||
// Matrix dimensions
|
||||
// (chosen as multiples of the thread block size for simplicity)
|
||||
#define WA (4 * block_size) // Matrix A width
|
||||
#define HA (6 * block_size) // Matrix A height
|
||||
#define WB (4 * block_size) // Matrix B width
|
||||
#define HB WA // Matrix B height
|
||||
#define WC WB // Matrix C width
|
||||
#define HC HA // Matrix C height
|
||||
|
||||
#endif // _MATRIXMUL_H_
|
||||
335
cpp/0_Introduction/matrixMulDrv/matrixMulDrv.cpp
Normal file
335
cpp/0_Introduction/matrixMulDrv/matrixMulDrv.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
/* Matrix multiplication: C = A * B.
|
||||
* Host code.
|
||||
*
|
||||
* This sample implements matrix multiplication using the CUDA driver API.
|
||||
* It has been written for clarity of exposition to illustrate various CUDA
|
||||
* programming principles, not with the goal of providing the most
|
||||
* performant generic kernel for matrix multiplication.
|
||||
*
|
||||
* CUBLAS provides high-performance matrix multiplication.
|
||||
* See also:
|
||||
* V. Volkov and J. Demmel, "Benchmarking GPUs to tune dense linear algebra,"
|
||||
* in Proc. 2008 ACM/IEEE Conf. on Supercomputing (SC '08),
|
||||
* Piscataway, NJ: IEEE Press, 2008, pp. Art. 31:1-11.
|
||||
*
|
||||
* Volkov, V. 2010. Better performance at lower occupancy,
|
||||
* GPU Technology Conference 2~010 (GTC 2010).
|
||||
*
|
||||
*/
|
||||
|
||||
// includes, system
|
||||
#include <builtin_types.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// includes, project, CUDA
|
||||
#include <cstring>
|
||||
#include <cuda.h>
|
||||
#include <helper_cuda_drvapi.h>
|
||||
#include <helper_image.h>
|
||||
#include <helper_string.h>
|
||||
#include <helper_timer.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "matrixMul.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// declaration, forward
|
||||
void runTest(int argc, char **argv);
|
||||
void randomInit(float *, int);
|
||||
|
||||
extern "C" void computeGold(float *, const float *, const float *, unsigned int, unsigned int, unsigned int);
|
||||
|
||||
static int initCUDA(int argc, char **argv, CUfunction *pMatrixMul, int *blk_size);
|
||||
|
||||
#ifndef FATBIN_FILE
|
||||
#define FATBIN_FILE "matrixMul_kernel64.fatbin"
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Globals
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CUdevice cuDevice;
|
||||
CUcontext cuContext;
|
||||
CUmodule cuModule;
|
||||
size_t totalGlobalMem;
|
||||
|
||||
const char *sSDKsample = "matrixMulDrv (Driver API)";
|
||||
|
||||
void constantInit(float *data, int size, float val)
|
||||
{
|
||||
for (int i = 0; i < size; ++i) {
|
||||
data[i] = val;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Program main
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
printf("[ %s ]\n", sSDKsample);
|
||||
|
||||
runTest(argc, argv);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Run a simple test for CUDA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void runTest(int argc, char **argv)
|
||||
{
|
||||
// initialize CUDA
|
||||
CUfunction matrixMul = NULL;
|
||||
int block_size = 0;
|
||||
|
||||
initCUDA(argc, argv, &matrixMul, &block_size);
|
||||
|
||||
// set seed for rand()
|
||||
srand(2006);
|
||||
|
||||
// allocate host memory for matrices A and B
|
||||
unsigned int size_A = WA * HA;
|
||||
unsigned int mem_size_A = sizeof(float) * size_A;
|
||||
float *h_A = reinterpret_cast<float *>(malloc(mem_size_A));
|
||||
unsigned int size_B = WB * HB;
|
||||
unsigned int mem_size_B = sizeof(float) * size_B;
|
||||
float *h_B = reinterpret_cast<float *>(malloc(mem_size_B));
|
||||
|
||||
// initialize host memory
|
||||
const float valB = 0.01f;
|
||||
constantInit(h_A, size_A, 1.0f);
|
||||
constantInit(h_B, size_B, valB);
|
||||
|
||||
// allocate device memory
|
||||
CUdeviceptr d_A;
|
||||
checkCudaErrors(cuMemAlloc(&d_A, mem_size_A));
|
||||
CUdeviceptr d_B;
|
||||
checkCudaErrors(cuMemAlloc(&d_B, mem_size_B));
|
||||
|
||||
// copy host memory to device
|
||||
checkCudaErrors(cuMemcpyHtoD(d_A, h_A, mem_size_A));
|
||||
checkCudaErrors(cuMemcpyHtoD(d_B, h_B, mem_size_B));
|
||||
|
||||
// allocate device memory for result
|
||||
size_t size_C = WC * HC;
|
||||
size_t mem_size_C = sizeof(float) * size_C;
|
||||
|
||||
CUdeviceptr d_C;
|
||||
checkCudaErrors(cuMemAlloc(&d_C, mem_size_C));
|
||||
|
||||
// allocate mem for the result on host side
|
||||
float *h_C = reinterpret_cast<float *>(malloc(mem_size_C));
|
||||
|
||||
// create and start timer
|
||||
StopWatchInterface *timer = NULL;
|
||||
sdkCreateTimer(&timer);
|
||||
|
||||
// start the timer
|
||||
sdkStartTimer(&timer);
|
||||
|
||||
// There are two ways to launch CUDA kernels via the Driver API.
|
||||
// In this CUDA Sample, we illustrate both ways to pass parameters
|
||||
// and specify parameters. By default we use the simpler method.
|
||||
dim3 block(block_size, block_size, 1);
|
||||
dim3 grid(WC / block_size, HC / block_size, 1);
|
||||
|
||||
if (1) {
|
||||
// This is the new CUDA 4.0 API for Kernel Parameter passing and Kernel
|
||||
// Launching (simplier method)
|
||||
size_t Matrix_Width_A = (size_t)WA;
|
||||
size_t Matrix_Width_B = (size_t)WB;
|
||||
void *args[5] = {&d_C, &d_A, &d_B, &Matrix_Width_A, &Matrix_Width_B};
|
||||
// new CUDA 4.0 Driver API Kernel launch call
|
||||
checkCudaErrors(cuLaunchKernel(matrixMul,
|
||||
grid.x,
|
||||
grid.y,
|
||||
grid.z,
|
||||
block.x,
|
||||
block.y,
|
||||
block.z,
|
||||
2 * block_size * block_size * sizeof(float),
|
||||
NULL,
|
||||
args,
|
||||
NULL));
|
||||
}
|
||||
else {
|
||||
// This is the new CUDA 4.0 API for Kernel Parameter passing and Kernel
|
||||
// Launching (advanced method)
|
||||
int offset = 0;
|
||||
char argBuffer[256];
|
||||
|
||||
// pass in launch parameters (not actually de-referencing CUdeviceptr).
|
||||
// CUdeviceptr is storing the value of the parameters
|
||||
*(reinterpret_cast<CUdeviceptr *>(&argBuffer[offset])) = d_C;
|
||||
offset += sizeof(d_C);
|
||||
*(reinterpret_cast<CUdeviceptr *>(&argBuffer[offset])) = d_A;
|
||||
offset += sizeof(d_A);
|
||||
*(reinterpret_cast<CUdeviceptr *>(&argBuffer[offset])) = d_B;
|
||||
offset += sizeof(d_B);
|
||||
|
||||
size_t Matrix_Width_A = (size_t)WA;
|
||||
size_t Matrix_Width_B = (size_t)WB;
|
||||
|
||||
*(reinterpret_cast<CUdeviceptr *>(&argBuffer[offset])) = Matrix_Width_A;
|
||||
offset += sizeof(Matrix_Width_A);
|
||||
*(reinterpret_cast<CUdeviceptr *>(&argBuffer[offset])) = Matrix_Width_B;
|
||||
offset += sizeof(Matrix_Width_B);
|
||||
|
||||
void *kernel_launch_config[5] = {
|
||||
CU_LAUNCH_PARAM_BUFFER_POINTER, argBuffer, CU_LAUNCH_PARAM_BUFFER_SIZE, &offset, CU_LAUNCH_PARAM_END};
|
||||
|
||||
// new CUDA 4.0 Driver API Kernel launch call
|
||||
checkCudaErrors(cuLaunchKernel(matrixMul,
|
||||
grid.x,
|
||||
grid.y,
|
||||
grid.z,
|
||||
block.x,
|
||||
block.y,
|
||||
block.z,
|
||||
2 * block_size * block_size * sizeof(float),
|
||||
NULL,
|
||||
NULL,
|
||||
reinterpret_cast<void **>(&kernel_launch_config)));
|
||||
}
|
||||
|
||||
// copy result from device to host
|
||||
checkCudaErrors(cuMemcpyDtoH(reinterpret_cast<void *>(h_C), d_C, mem_size_C));
|
||||
|
||||
// stop and destroy timer
|
||||
sdkStopTimer(&timer);
|
||||
printf("Processing time: %f (ms)\n", sdkGetTimerValue(&timer));
|
||||
sdkDeleteTimer(&timer);
|
||||
|
||||
printf("Checking computed result for correctness: ");
|
||||
bool correct = true;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(WC * HC); i++) {
|
||||
if (fabs(h_C[i] - (WA * valB)) > 1e-5) {
|
||||
printf("Error! Matrix[%05d]=%.8f, ref=%.8f error term is > 1e-5\n", i, h_C[i], WA * valB);
|
||||
correct = false;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s\n", correct ? "Result = PASS" : "Result = FAIL");
|
||||
|
||||
printf("\nNOTE: The CUDA Samples are not meant for performance measurements. "
|
||||
"Results may vary when GPU Boost is enabled.\n");
|
||||
|
||||
// clean up memory
|
||||
free(h_A);
|
||||
free(h_B);
|
||||
free(h_C);
|
||||
checkCudaErrors(cuMemFree(d_A));
|
||||
checkCudaErrors(cuMemFree(d_B));
|
||||
checkCudaErrors(cuMemFree(d_C));
|
||||
checkCudaErrors(cuModuleUnload(cuModule));
|
||||
checkCudaErrors(cuCtxDestroy(cuContext));
|
||||
}
|
||||
|
||||
// Allocates a matrix with random float entries.
|
||||
void randomInit(float *data, int size)
|
||||
{
|
||||
for (int i = 0; i < size; ++i) {
|
||||
data[i] = rand() / static_cast<float>(RAND_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static int initCUDA(int argc, char **argv, CUfunction *pMatrixMul, int *blk_size)
|
||||
{
|
||||
CUfunction cuFunction = 0;
|
||||
int major = 0, minor = 0;
|
||||
char deviceName[100];
|
||||
CUctxCreateParams ctxCreateParams = {};
|
||||
|
||||
cuDevice = findCudaDeviceDRV(argc, (const char **)argv);
|
||||
|
||||
// get compute capabilities and the devicename
|
||||
checkCudaErrors(cuDeviceGetAttribute(&major, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MAJOR, cuDevice));
|
||||
checkCudaErrors(cuDeviceGetAttribute(&minor, CU_DEVICE_ATTRIBUTE_COMPUTE_CAPABILITY_MINOR, cuDevice));
|
||||
checkCudaErrors(cuDeviceGetName(deviceName, sizeof(deviceName), cuDevice));
|
||||
printf("> GPU Device has SM %d.%d compute capability\n", major, minor);
|
||||
|
||||
checkCudaErrors(cuDeviceTotalMem(&totalGlobalMem, cuDevice));
|
||||
printf(" Total amount of global memory: %llu bytes\n", (long long unsigned int)totalGlobalMem);
|
||||
|
||||
checkCudaErrors(cuCtxCreate(&cuContext, &ctxCreateParams, 0, cuDevice));
|
||||
|
||||
// first search for the module path before we load the results
|
||||
std::string module_path;
|
||||
std::ostringstream fatbin;
|
||||
|
||||
if (!findFatbinPath(FATBIN_FILE, module_path, argv, fatbin)) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else {
|
||||
printf("> initCUDA loading module: <%s>\n", module_path.c_str());
|
||||
}
|
||||
|
||||
if (!fatbin.str().size()) {
|
||||
printf("fatbin file empty. exiting..\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Create module from binary file (FATBIN)
|
||||
checkCudaErrors(cuModuleLoadData(&cuModule, fatbin.str().c_str()));
|
||||
|
||||
// select the suitable kernel function
|
||||
const char *kernels[] = {"matrixMul_bs32_64bit", "matrixMul_bs16_64bit", "matrixMul_bs8_64bit"};
|
||||
|
||||
int idx = 0;
|
||||
int block_size = 32;
|
||||
while (idx < 3) {
|
||||
int threadsPerBlock = 0;
|
||||
int blocksPerGrid = 0;
|
||||
|
||||
checkCudaErrors(cuModuleGetFunction(&cuFunction, cuModule, kernels[idx]));
|
||||
checkCudaErrors(cuOccupancyMaxPotentialBlockSize(
|
||||
&blocksPerGrid, &threadsPerBlock, cuFunction, 0, 2 * block_size * block_size * sizeof(float), 0));
|
||||
if (block_size * block_size <= threadsPerBlock) {
|
||||
printf("> %d block size selected\n", block_size);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
block_size /= 2;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
*pMatrixMul = cuFunction;
|
||||
*blk_size = block_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
128
cpp/0_Introduction/matrixMulDrv/matrixMul_kernel.cu
Normal file
128
cpp/0_Introduction/matrixMulDrv/matrixMul_kernel.cu
Normal file
@@ -0,0 +1,128 @@
|
||||
/* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
/* Matrix multiplication: C = A * B.
|
||||
* Device code.
|
||||
*/
|
||||
|
||||
#ifndef _MATRIXMUL_KERNEL_H_
|
||||
#define _MATRIXMUL_KERNEL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define AS(i, j) As[i][j]
|
||||
#define BS(i, j) Bs[i][j]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//! Matrix multiplication on the device: C = A * B
|
||||
//! wA is A's width and wB is B's width
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <int block_size, typename size_type>
|
||||
__device__ void matrixMul(float *C, float *A, float *B, size_type wA, size_type wB)
|
||||
{
|
||||
// Block index
|
||||
size_type bx = blockIdx.x;
|
||||
size_type by = blockIdx.y;
|
||||
|
||||
// Thread index
|
||||
size_type tx = threadIdx.x;
|
||||
size_type ty = threadIdx.y;
|
||||
|
||||
// Index of the first sub-matrix of A processed by the block
|
||||
size_type aBegin = wA * block_size * by;
|
||||
|
||||
// Index of the last sub-matrix of A processed by the block
|
||||
size_type aEnd = aBegin + wA - 1;
|
||||
|
||||
// Step size used to iterate through the sub-matrices of A
|
||||
size_type aStep = block_size;
|
||||
|
||||
// Index of the first sub-matrix of B processed by the block
|
||||
size_type bBegin = block_size * bx;
|
||||
|
||||
// Step size used to iterate through the sub-matrices of B
|
||||
size_type bStep = block_size * wB;
|
||||
|
||||
// Csub is used to store the element of the block sub-matrix
|
||||
// that is computed by the thread
|
||||
float Csub = 0;
|
||||
|
||||
// Loop over all the sub-matrices of A and B
|
||||
// required to compute the block sub-matrix
|
||||
for (size_type a = aBegin, b = bBegin; a <= aEnd; a += aStep, b += bStep) {
|
||||
// Declaration of the shared memory array As used to
|
||||
// store the sub-matrix of A
|
||||
__shared__ float As[block_size][block_size];
|
||||
|
||||
// Declaration of the shared memory array Bs used to
|
||||
// store the sub-matrix of B
|
||||
__shared__ float Bs[block_size][block_size];
|
||||
|
||||
// Load the matrices from device memory
|
||||
// to shared memory; each thread loads
|
||||
// one element of each matrix
|
||||
AS(ty, tx) = A[a + wA * ty + tx];
|
||||
BS(ty, tx) = B[b + wB * ty + tx];
|
||||
|
||||
// Synchronize to make sure the matrices are loaded
|
||||
__syncthreads();
|
||||
|
||||
// Multiply the two matrices together;
|
||||
// each thread computes one element
|
||||
// of the block sub-matrix
|
||||
#pragma unroll
|
||||
|
||||
for (size_type k = 0; k < block_size; ++k)
|
||||
Csub += AS(ty, k) * BS(k, tx);
|
||||
|
||||
// Synchronize to make sure that the preceding
|
||||
// computation is done before loading two new
|
||||
// sub-matrices of A and B in the next iteration
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
// Write the block sub-matrix to device memory;
|
||||
// each thread writes one element
|
||||
size_type c = wB * block_size * by + block_size * bx;
|
||||
C[c + wB * ty + tx] = Csub;
|
||||
}
|
||||
|
||||
// C wrappers around our template kernel
|
||||
extern "C" __global__ void matrixMul_bs8_64bit(float *C, float *A, float *B, size_t wA, size_t wB)
|
||||
{
|
||||
matrixMul<8, size_t>(C, A, B, wA, wB);
|
||||
}
|
||||
extern "C" __global__ void matrixMul_bs16_64bit(float *C, float *A, float *B, size_t wA, size_t wB)
|
||||
{
|
||||
matrixMul<16, size_t>(C, A, B, wA, wB);
|
||||
}
|
||||
extern "C" __global__ void matrixMul_bs32_64bit(float *C, float *A, float *B, size_t wA, size_t wB)
|
||||
{
|
||||
matrixMul<32, size_t>(C, A, B, wA, wB);
|
||||
}
|
||||
|
||||
#endif // #ifndef _MATRIXMUL_KERNEL_H_
|
||||
Reference in New Issue
Block a user