Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.

This commit is contained in:
Rob Armstrong
2025-03-27 10:30:07 -07:00
parent 2cd58fbc9a
commit ceab6e8bcc
782 changed files with 107230 additions and 106548 deletions

View File

@@ -26,8 +26,8 @@
*/
#include <assert.h>
#include <helper_cuda.h>
#include <cooperative_groups.h>
#include <helper_cuda.h>
namespace cg = cooperative_groups;
#include "convolutionSeparable_common.h"
@@ -37,178 +37,156 @@ namespace cg = cooperative_groups;
////////////////////////////////////////////////////////////////////////////////
__constant__ float c_Kernel[KERNEL_LENGTH];
extern "C" void setConvolutionKernel(float *h_Kernel) {
cudaMemcpyToSymbol(c_Kernel, h_Kernel, KERNEL_LENGTH * sizeof(float));
extern "C" void setConvolutionKernel(float *h_Kernel)
{
cudaMemcpyToSymbol(c_Kernel, h_Kernel, KERNEL_LENGTH * sizeof(float));
}
////////////////////////////////////////////////////////////////////////////////
// Row convolution filter
////////////////////////////////////////////////////////////////////////////////
#define ROWS_BLOCKDIM_X 16
#define ROWS_BLOCKDIM_Y 4
#define ROWS_BLOCKDIM_X 16
#define ROWS_BLOCKDIM_Y 4
#define ROWS_RESULT_STEPS 8
#define ROWS_HALO_STEPS 1
#define ROWS_HALO_STEPS 1
__global__ void convolutionRowsKernel(float *d_Dst, float *d_Src, int imageW,
int imageH, int pitch) {
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
__shared__ float
s_Data[ROWS_BLOCKDIM_Y][(ROWS_RESULT_STEPS + 2 * ROWS_HALO_STEPS) *
ROWS_BLOCKDIM_X];
__global__ void convolutionRowsKernel(float *d_Dst, float *d_Src, int imageW, int imageH, int pitch)
{
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
__shared__ float s_Data[ROWS_BLOCKDIM_Y][(ROWS_RESULT_STEPS + 2 * ROWS_HALO_STEPS) * ROWS_BLOCKDIM_X];
// Offset to the left halo edge
const int baseX =
(blockIdx.x * ROWS_RESULT_STEPS - ROWS_HALO_STEPS) * ROWS_BLOCKDIM_X +
threadIdx.x;
const int baseY = blockIdx.y * ROWS_BLOCKDIM_Y + threadIdx.y;
// Offset to the left halo edge
const int baseX = (blockIdx.x * ROWS_RESULT_STEPS - ROWS_HALO_STEPS) * ROWS_BLOCKDIM_X + threadIdx.x;
const int baseY = blockIdx.y * ROWS_BLOCKDIM_Y + threadIdx.y;
d_Src += baseY * pitch + baseX;
d_Dst += baseY * pitch + baseX;
d_Src += baseY * pitch + baseX;
d_Dst += baseY * pitch + baseX;
// Load main data
#pragma unroll
for (int i = ROWS_HALO_STEPS; i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] =
d_Src[i * ROWS_BLOCKDIM_X];
}
for (int i = ROWS_HALO_STEPS; i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] = d_Src[i * ROWS_BLOCKDIM_X];
}
// Load left halo
#pragma unroll
for (int i = 0; i < ROWS_HALO_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] =
(baseX >= -i * ROWS_BLOCKDIM_X) ? d_Src[i * ROWS_BLOCKDIM_X] : 0;
}
for (int i = 0; i < ROWS_HALO_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] =
(baseX >= -i * ROWS_BLOCKDIM_X) ? d_Src[i * ROWS_BLOCKDIM_X] : 0;
}
// Load right halo
#pragma unroll
for (int i = ROWS_HALO_STEPS + ROWS_RESULT_STEPS;
i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS + ROWS_HALO_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] =
(imageW - baseX > i * ROWS_BLOCKDIM_X) ? d_Src[i * ROWS_BLOCKDIM_X] : 0;
}
// Compute and store results
cg::sync(cta);
#pragma unroll
for (int i = ROWS_HALO_STEPS; i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS; i++) {
float sum = 0;
#pragma unroll
for (int j = -KERNEL_RADIUS; j <= KERNEL_RADIUS; j++) {
sum += c_Kernel[KERNEL_RADIUS - j] *
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X + j];
for (int i = ROWS_HALO_STEPS + ROWS_RESULT_STEPS; i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS + ROWS_HALO_STEPS; i++) {
s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X] =
(imageW - baseX > i * ROWS_BLOCKDIM_X) ? d_Src[i * ROWS_BLOCKDIM_X] : 0;
}
d_Dst[i * ROWS_BLOCKDIM_X] = sum;
}
// Compute and store results
cg::sync(cta);
#pragma unroll
for (int i = ROWS_HALO_STEPS; i < ROWS_HALO_STEPS + ROWS_RESULT_STEPS; i++) {
float sum = 0;
#pragma unroll
for (int j = -KERNEL_RADIUS; j <= KERNEL_RADIUS; j++) {
sum += c_Kernel[KERNEL_RADIUS - j] * s_Data[threadIdx.y][threadIdx.x + i * ROWS_BLOCKDIM_X + j];
}
d_Dst[i * ROWS_BLOCKDIM_X] = sum;
}
}
extern "C" void convolutionRowsGPU(float *d_Dst, float *d_Src, int imageW,
int imageH) {
assert(ROWS_BLOCKDIM_X * ROWS_HALO_STEPS >= KERNEL_RADIUS);
assert(imageW % (ROWS_RESULT_STEPS * ROWS_BLOCKDIM_X) == 0);
assert(imageH % ROWS_BLOCKDIM_Y == 0);
extern "C" void convolutionRowsGPU(float *d_Dst, float *d_Src, int imageW, int imageH)
{
assert(ROWS_BLOCKDIM_X * ROWS_HALO_STEPS >= KERNEL_RADIUS);
assert(imageW % (ROWS_RESULT_STEPS * ROWS_BLOCKDIM_X) == 0);
assert(imageH % ROWS_BLOCKDIM_Y == 0);
dim3 blocks(imageW / (ROWS_RESULT_STEPS * ROWS_BLOCKDIM_X),
imageH / ROWS_BLOCKDIM_Y);
dim3 threads(ROWS_BLOCKDIM_X, ROWS_BLOCKDIM_Y);
dim3 blocks(imageW / (ROWS_RESULT_STEPS * ROWS_BLOCKDIM_X), imageH / ROWS_BLOCKDIM_Y);
dim3 threads(ROWS_BLOCKDIM_X, ROWS_BLOCKDIM_Y);
convolutionRowsKernel<<<blocks, threads>>>(d_Dst, d_Src, imageW, imageH,
imageW);
getLastCudaError("convolutionRowsKernel() execution failed\n");
convolutionRowsKernel<<<blocks, threads>>>(d_Dst, d_Src, imageW, imageH, imageW);
getLastCudaError("convolutionRowsKernel() execution failed\n");
}
////////////////////////////////////////////////////////////////////////////////
// Column convolution filter
////////////////////////////////////////////////////////////////////////////////
#define COLUMNS_BLOCKDIM_X 16
#define COLUMNS_BLOCKDIM_Y 8
#define COLUMNS_BLOCKDIM_X 16
#define COLUMNS_BLOCKDIM_Y 8
#define COLUMNS_RESULT_STEPS 8
#define COLUMNS_HALO_STEPS 1
#define COLUMNS_HALO_STEPS 1
__global__ void convolutionColumnsKernel(float *d_Dst, float *d_Src, int imageW,
int imageH, int pitch) {
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
__shared__ float s_Data[COLUMNS_BLOCKDIM_X][(COLUMNS_RESULT_STEPS +
2 * COLUMNS_HALO_STEPS) *
COLUMNS_BLOCKDIM_Y +
1];
__global__ void convolutionColumnsKernel(float *d_Dst, float *d_Src, int imageW, int imageH, int pitch)
{
// Handle to thread block group
cg::thread_block cta = cg::this_thread_block();
__shared__ float s_Data[COLUMNS_BLOCKDIM_X]
[(COLUMNS_RESULT_STEPS + 2 * COLUMNS_HALO_STEPS) * COLUMNS_BLOCKDIM_Y + 1];
// Offset to the upper halo edge
const int baseX = blockIdx.x * COLUMNS_BLOCKDIM_X + threadIdx.x;
const int baseY = (blockIdx.y * COLUMNS_RESULT_STEPS - COLUMNS_HALO_STEPS) *
COLUMNS_BLOCKDIM_Y +
threadIdx.y;
d_Src += baseY * pitch + baseX;
d_Dst += baseY * pitch + baseX;
// Offset to the upper halo edge
const int baseX = blockIdx.x * COLUMNS_BLOCKDIM_X + threadIdx.x;
const int baseY = (blockIdx.y * COLUMNS_RESULT_STEPS - COLUMNS_HALO_STEPS) * COLUMNS_BLOCKDIM_Y + threadIdx.y;
d_Src += baseY * pitch + baseX;
d_Dst += baseY * pitch + baseX;
// Main data
#pragma unroll
for (int i = COLUMNS_HALO_STEPS;
i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS; i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] =
d_Src[i * COLUMNS_BLOCKDIM_Y * pitch];
}
for (int i = COLUMNS_HALO_STEPS; i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS; i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] = d_Src[i * COLUMNS_BLOCKDIM_Y * pitch];
}
// Upper halo
#pragma unroll
for (int i = 0; i < COLUMNS_HALO_STEPS; i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] =
(baseY >= -i * COLUMNS_BLOCKDIM_Y)
? d_Src[i * COLUMNS_BLOCKDIM_Y * pitch]
: 0;
}
for (int i = 0; i < COLUMNS_HALO_STEPS; i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] =
(baseY >= -i * COLUMNS_BLOCKDIM_Y) ? d_Src[i * COLUMNS_BLOCKDIM_Y * pitch] : 0;
}
// Lower halo
#pragma unroll
for (int i = COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS;
i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS + COLUMNS_HALO_STEPS;
i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] =
(imageH - baseY > i * COLUMNS_BLOCKDIM_Y)
? d_Src[i * COLUMNS_BLOCKDIM_Y * pitch]
: 0;
}
// Compute and store results
cg::sync(cta);
#pragma unroll
for (int i = COLUMNS_HALO_STEPS;
i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS; i++) {
float sum = 0;
#pragma unroll
for (int j = -KERNEL_RADIUS; j <= KERNEL_RADIUS; j++) {
sum += c_Kernel[KERNEL_RADIUS - j] *
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y + j];
for (int i = COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS;
i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS + COLUMNS_HALO_STEPS;
i++) {
s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y] =
(imageH - baseY > i * COLUMNS_BLOCKDIM_Y) ? d_Src[i * COLUMNS_BLOCKDIM_Y * pitch] : 0;
}
d_Dst[i * COLUMNS_BLOCKDIM_Y * pitch] = sum;
}
// Compute and store results
cg::sync(cta);
#pragma unroll
for (int i = COLUMNS_HALO_STEPS; i < COLUMNS_HALO_STEPS + COLUMNS_RESULT_STEPS; i++) {
float sum = 0;
#pragma unroll
for (int j = -KERNEL_RADIUS; j <= KERNEL_RADIUS; j++) {
sum += c_Kernel[KERNEL_RADIUS - j] * s_Data[threadIdx.x][threadIdx.y + i * COLUMNS_BLOCKDIM_Y + j];
}
d_Dst[i * COLUMNS_BLOCKDIM_Y * pitch] = sum;
}
}
extern "C" void convolutionColumnsGPU(float *d_Dst, float *d_Src, int imageW,
int imageH) {
assert(COLUMNS_BLOCKDIM_Y * COLUMNS_HALO_STEPS >= KERNEL_RADIUS);
assert(imageW % COLUMNS_BLOCKDIM_X == 0);
assert(imageH % (COLUMNS_RESULT_STEPS * COLUMNS_BLOCKDIM_Y) == 0);
extern "C" void convolutionColumnsGPU(float *d_Dst, float *d_Src, int imageW, int imageH)
{
assert(COLUMNS_BLOCKDIM_Y * COLUMNS_HALO_STEPS >= KERNEL_RADIUS);
assert(imageW % COLUMNS_BLOCKDIM_X == 0);
assert(imageH % (COLUMNS_RESULT_STEPS * COLUMNS_BLOCKDIM_Y) == 0);
dim3 blocks(imageW / COLUMNS_BLOCKDIM_X,
imageH / (COLUMNS_RESULT_STEPS * COLUMNS_BLOCKDIM_Y));
dim3 threads(COLUMNS_BLOCKDIM_X, COLUMNS_BLOCKDIM_Y);
dim3 blocks(imageW / COLUMNS_BLOCKDIM_X, imageH / (COLUMNS_RESULT_STEPS * COLUMNS_BLOCKDIM_Y));
dim3 threads(COLUMNS_BLOCKDIM_X, COLUMNS_BLOCKDIM_Y);
convolutionColumnsKernel<<<blocks, threads>>>(d_Dst, d_Src, imageW, imageH,
imageW);
getLastCudaError("convolutionColumnsKernel() execution failed\n");
convolutionColumnsKernel<<<blocks, threads>>>(d_Dst, d_Src, imageW, imageH, imageW);
getLastCudaError("convolutionColumnsKernel() execution failed\n");
}

View File

@@ -34,22 +34,17 @@
////////////////////////////////////////////////////////////////////////////////
// Reference CPU convolution
////////////////////////////////////////////////////////////////////////////////
extern "C" void convolutionRowCPU(float *h_Dst, float *h_Src, float *h_Kernel,
int imageW, int imageH, int kernelR);
extern "C" void convolutionRowCPU(float *h_Dst, float *h_Src, float *h_Kernel, int imageW, int imageH, int kernelR);
extern "C" void convolutionColumnCPU(float *h_Dst, float *h_Src,
float *h_Kernel, int imageW, int imageH,
int kernelR);
extern "C" void convolutionColumnCPU(float *h_Dst, float *h_Src, float *h_Kernel, int imageW, int imageH, int kernelR);
////////////////////////////////////////////////////////////////////////////////
// GPU convolution
////////////////////////////////////////////////////////////////////////////////
extern "C" void setConvolutionKernel(float *h_Kernel);
extern "C" void convolutionRowsGPU(float *d_Dst, float *d_Src, int imageW,
int imageH);
extern "C" void convolutionRowsGPU(float *d_Dst, float *d_Src, int imageW, int imageH);
extern "C" void convolutionColumnsGPU(float *d_Dst, float *d_Src, int imageW,
int imageH);
extern "C" void convolutionColumnsGPU(float *d_Dst, float *d_Src, int imageW, int imageH);
#endif

View File

@@ -30,40 +30,39 @@
////////////////////////////////////////////////////////////////////////////////
// Reference row convolution filter
////////////////////////////////////////////////////////////////////////////////
extern "C" void convolutionRowCPU(float *h_Dst, float *h_Src, float *h_Kernel,
int imageW, int imageH, int kernelR) {
for (int y = 0; y < imageH; y++)
for (int x = 0; x < imageW; x++) {
float sum = 0;
extern "C" void convolutionRowCPU(float *h_Dst, float *h_Src, float *h_Kernel, int imageW, int imageH, int kernelR)
{
for (int y = 0; y < imageH; y++)
for (int x = 0; x < imageW; x++) {
float sum = 0;
for (int k = -kernelR; k <= kernelR; k++) {
int d = x + k;
for (int k = -kernelR; k <= kernelR; k++) {
int d = x + k;
if (d >= 0 && d < imageW)
sum += h_Src[y * imageW + d] * h_Kernel[kernelR - k];
}
if (d >= 0 && d < imageW)
sum += h_Src[y * imageW + d] * h_Kernel[kernelR - k];
}
h_Dst[y * imageW + x] = sum;
}
h_Dst[y * imageW + x] = sum;
}
}
////////////////////////////////////////////////////////////////////////////////
// Reference column convolution filter
////////////////////////////////////////////////////////////////////////////////
extern "C" void convolutionColumnCPU(float *h_Dst, float *h_Src,
float *h_Kernel, int imageW, int imageH,
int kernelR) {
for (int y = 0; y < imageH; y++)
for (int x = 0; x < imageW; x++) {
float sum = 0;
extern "C" void convolutionColumnCPU(float *h_Dst, float *h_Src, float *h_Kernel, int imageW, int imageH, int kernelR)
{
for (int y = 0; y < imageH; y++)
for (int x = 0; x < imageW; x++) {
float sum = 0;
for (int k = -kernelR; k <= kernelR; k++) {
int d = y + k;
for (int k = -kernelR; k <= kernelR; k++) {
int d = y + k;
if (d >= 0 && d < imageH)
sum += h_Src[d * imageW + x] * h_Kernel[kernelR - k];
}
if (d >= 0 && d < imageH)
sum += h_Src[d * imageW + x] * h_Kernel[kernelR - k];
}
h_Dst[y * imageW + x] = sum;
}
h_Dst[y * imageW + x] = sum;
}
}

View File

@@ -26,149 +26,140 @@
*/
/*
* This sample implements a separable convolution filter
* of a 2D image with an arbitrary kernel.
*/
* This sample implements a separable convolution filter
* of a 2D image with an arbitrary kernel.
*/
// CUDA runtime
#include <cuda_runtime.h>
// Utilities and system includes
#include <helper_functions.h>
#include <helper_cuda.h>
#include <helper_functions.h>
#include "convolutionSeparable_common.h"
////////////////////////////////////////////////////////////////////////////////
// Reference CPU convolution
////////////////////////////////////////////////////////////////////////////////
extern "C" void convolutionRowCPU(float *h_Result, float *h_Data,
float *h_Kernel, int imageW, int imageH,
int kernelR);
extern "C" void convolutionRowCPU(float *h_Result, float *h_Data, float *h_Kernel, int imageW, int imageH, int kernelR);
extern "C" void convolutionColumnCPU(float *h_Result, float *h_Data,
float *h_Kernel, int imageW, int imageH,
int kernelR);
extern "C" void
convolutionColumnCPU(float *h_Result, float *h_Data, float *h_Kernel, int imageW, int imageH, int kernelR);
////////////////////////////////////////////////////////////////////////////////
// Main program
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
// start logs
printf("[%s] - Starting...\n", argv[0]);
int main(int argc, char **argv)
{
// start logs
printf("[%s] - Starting...\n", argv[0]);
float *h_Kernel, *h_Input, *h_Buffer, *h_OutputCPU, *h_OutputGPU;
float *h_Kernel, *h_Input, *h_Buffer, *h_OutputCPU, *h_OutputGPU;
float *d_Input, *d_Output, *d_Buffer;
float *d_Input, *d_Output, *d_Buffer;
const int imageW = 3072;
const int imageH = 3072;
const int iterations = 16;
const int imageW = 3072;
const int imageH = 3072;
const int iterations = 16;
StopWatchInterface *hTimer = NULL;
StopWatchInterface *hTimer = NULL;
// Use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
findCudaDevice(argc, (const char **)argv);
// Use command-line specified CUDA device, otherwise use device with highest
// Gflops/s
findCudaDevice(argc, (const char **)argv);
sdkCreateTimer(&hTimer);
sdkCreateTimer(&hTimer);
printf("Image Width x Height = %i x %i\n\n", imageW, imageH);
printf("Allocating and initializing host arrays...\n");
h_Kernel = (float *)malloc(KERNEL_LENGTH * sizeof(float));
h_Input = (float *)malloc(imageW * imageH * sizeof(float));
h_Buffer = (float *)malloc(imageW * imageH * sizeof(float));
h_OutputCPU = (float *)malloc(imageW * imageH * sizeof(float));
h_OutputGPU = (float *)malloc(imageW * imageH * sizeof(float));
srand(200);
printf("Image Width x Height = %i x %i\n\n", imageW, imageH);
printf("Allocating and initializing host arrays...\n");
h_Kernel = (float *)malloc(KERNEL_LENGTH * sizeof(float));
h_Input = (float *)malloc(imageW * imageH * sizeof(float));
h_Buffer = (float *)malloc(imageW * imageH * sizeof(float));
h_OutputCPU = (float *)malloc(imageW * imageH * sizeof(float));
h_OutputGPU = (float *)malloc(imageW * imageH * sizeof(float));
srand(200);
for (unsigned int i = 0; i < KERNEL_LENGTH; i++) {
h_Kernel[i] = (float)(rand() % 16);
}
for (unsigned i = 0; i < imageW * imageH; i++) {
h_Input[i] = (float)(rand() % 16);
}
printf("Allocating and initializing CUDA arrays...\n");
checkCudaErrors(
cudaMalloc((void **)&d_Input, imageW * imageH * sizeof(float)));
checkCudaErrors(
cudaMalloc((void **)&d_Output, imageW * imageH * sizeof(float)));
checkCudaErrors(
cudaMalloc((void **)&d_Buffer, imageW * imageH * sizeof(float)));
setConvolutionKernel(h_Kernel);
checkCudaErrors(cudaMemcpy(d_Input, h_Input, imageW * imageH * sizeof(float),
cudaMemcpyHostToDevice));
printf("Running GPU convolution (%u identical iterations)...\n\n",
iterations);
for (int i = -1; i < iterations; i++) {
// i == -1 -- warmup iteration
if (i == 0) {
checkCudaErrors(cudaDeviceSynchronize());
sdkResetTimer(&hTimer);
sdkStartTimer(&hTimer);
for (unsigned int i = 0; i < KERNEL_LENGTH; i++) {
h_Kernel[i] = (float)(rand() % 16);
}
convolutionRowsGPU(d_Buffer, d_Input, imageW, imageH);
for (unsigned i = 0; i < imageW * imageH; i++) {
h_Input[i] = (float)(rand() % 16);
}
convolutionColumnsGPU(d_Output, d_Buffer, imageW, imageH);
}
printf("Allocating and initializing CUDA arrays...\n");
checkCudaErrors(cudaMalloc((void **)&d_Input, imageW * imageH * sizeof(float)));
checkCudaErrors(cudaMalloc((void **)&d_Output, imageW * imageH * sizeof(float)));
checkCudaErrors(cudaMalloc((void **)&d_Buffer, imageW * imageH * sizeof(float)));
checkCudaErrors(cudaDeviceSynchronize());
sdkStopTimer(&hTimer);
double gpuTime = 0.001 * sdkGetTimerValue(&hTimer) / (double)iterations;
printf(
"convolutionSeparable, Throughput = %.4f MPixels/sec, Time = %.5f s, "
"Size = %u Pixels, NumDevsUsed = %i, Workgroup = %u\n",
(1.0e-6 * (double)(imageW * imageH) / gpuTime), gpuTime,
(imageW * imageH), 1, 0);
setConvolutionKernel(h_Kernel);
checkCudaErrors(cudaMemcpy(d_Input, h_Input, imageW * imageH * sizeof(float), cudaMemcpyHostToDevice));
printf("\nReading back GPU results...\n\n");
checkCudaErrors(cudaMemcpy(h_OutputGPU, d_Output,
imageW * imageH * sizeof(float),
cudaMemcpyDeviceToHost));
printf("Running GPU convolution (%u identical iterations)...\n\n", iterations);
printf("Checking the results...\n");
printf(" ...running convolutionRowCPU()\n");
convolutionRowCPU(h_Buffer, h_Input, h_Kernel, imageW, imageH, KERNEL_RADIUS);
for (int i = -1; i < iterations; i++) {
// i == -1 -- warmup iteration
if (i == 0) {
checkCudaErrors(cudaDeviceSynchronize());
sdkResetTimer(&hTimer);
sdkStartTimer(&hTimer);
}
printf(" ...running convolutionColumnCPU()\n");
convolutionColumnCPU(h_OutputCPU, h_Buffer, h_Kernel, imageW, imageH,
KERNEL_RADIUS);
convolutionRowsGPU(d_Buffer, d_Input, imageW, imageH);
printf(" ...comparing the results\n");
double sum = 0, delta = 0;
convolutionColumnsGPU(d_Output, d_Buffer, imageW, imageH);
}
for (unsigned i = 0; i < imageW * imageH; i++) {
delta +=
(h_OutputGPU[i] - h_OutputCPU[i]) * (h_OutputGPU[i] - h_OutputCPU[i]);
sum += h_OutputCPU[i] * h_OutputCPU[i];
}
checkCudaErrors(cudaDeviceSynchronize());
sdkStopTimer(&hTimer);
double gpuTime = 0.001 * sdkGetTimerValue(&hTimer) / (double)iterations;
printf("convolutionSeparable, Throughput = %.4f MPixels/sec, Time = %.5f s, "
"Size = %u Pixels, NumDevsUsed = %i, Workgroup = %u\n",
(1.0e-6 * (double)(imageW * imageH) / gpuTime),
gpuTime,
(imageW * imageH),
1,
0);
double L2norm = sqrt(delta / sum);
printf(" ...Relative L2 norm: %E\n\n", L2norm);
printf("Shutting down...\n");
printf("\nReading back GPU results...\n\n");
checkCudaErrors(cudaMemcpy(h_OutputGPU, d_Output, imageW * imageH * sizeof(float), cudaMemcpyDeviceToHost));
checkCudaErrors(cudaFree(d_Buffer));
checkCudaErrors(cudaFree(d_Output));
checkCudaErrors(cudaFree(d_Input));
free(h_OutputGPU);
free(h_OutputCPU);
free(h_Buffer);
free(h_Input);
free(h_Kernel);
printf("Checking the results...\n");
printf(" ...running convolutionRowCPU()\n");
convolutionRowCPU(h_Buffer, h_Input, h_Kernel, imageW, imageH, KERNEL_RADIUS);
sdkDeleteTimer(&hTimer);
printf(" ...running convolutionColumnCPU()\n");
convolutionColumnCPU(h_OutputCPU, h_Buffer, h_Kernel, imageW, imageH, KERNEL_RADIUS);
if (L2norm > 1e-6) {
printf("Test failed!\n");
exit(EXIT_FAILURE);
}
printf(" ...comparing the results\n");
double sum = 0, delta = 0;
printf("Test passed\n");
exit(EXIT_SUCCESS);
for (unsigned i = 0; i < imageW * imageH; i++) {
delta += (h_OutputGPU[i] - h_OutputCPU[i]) * (h_OutputGPU[i] - h_OutputCPU[i]);
sum += h_OutputCPU[i] * h_OutputCPU[i];
}
double L2norm = sqrt(delta / sum);
printf(" ...Relative L2 norm: %E\n\n", L2norm);
printf("Shutting down...\n");
checkCudaErrors(cudaFree(d_Buffer));
checkCudaErrors(cudaFree(d_Output));
checkCudaErrors(cudaFree(d_Input));
free(h_OutputGPU);
free(h_OutputCPU);
free(h_Buffer);
free(h_Input);
free(h_Kernel);
sdkDeleteTimer(&hTimer);
if (L2norm > 1e-6) {
printf("Test failed!\n");
exit(EXIT_FAILURE);
}
printf("Test passed\n");
exit(EXIT_SUCCESS);
}