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

@@ -65,9 +65,9 @@
#include <cuda_runtime.h>
// Utilities and system includes
#include <algorithm>
#include <helper_cuda.h>
#include <helper_functions.h>
#include <algorithm>
// includes, project
#include "reduction.h"
@@ -76,8 +76,7 @@ enum ReduceType { REDUCE_INT, REDUCE_FLOAT, REDUCE_DOUBLE };
////////////////////////////////////////////////////////////////////////////////
// declaration, forward
template <class T>
bool runTest(int argc, char **argv, ReduceType datatype);
template <class T> bool runTest(int argc, char **argv, ReduceType datatype);
#define MAX_BLOCK_DIM_SIZE 65535
@@ -87,71 +86,74 @@ bool runTest(int argc, char **argv, ReduceType datatype);
extern "C" bool isPow2(unsigned int x) { return ((x & (x - 1)) == 0); }
const char *getReduceTypeString(const ReduceType type) {
switch (type) {
const char *getReduceTypeString(const ReduceType type)
{
switch (type) {
case REDUCE_INT:
return "int";
return "int";
case REDUCE_FLOAT:
return "float";
return "float";
case REDUCE_DOUBLE:
return "double";
return "double";
default:
return "unknown";
}
return "unknown";
}
}
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv) {
printf("%s Starting...\n\n", argv[0]);
int main(int argc, char **argv)
{
printf("%s Starting...\n\n", argv[0]);
char *typeInput = 0;
getCmdLineArgumentString(argc, (const char **)argv, "type", &typeInput);
char *typeInput = 0;
getCmdLineArgumentString(argc, (const char **)argv, "type", &typeInput);
ReduceType datatype = REDUCE_INT;
ReduceType datatype = REDUCE_INT;
if (0 != typeInput) {
if (!strcasecmp(typeInput, "float")) {
datatype = REDUCE_FLOAT;
} else if (!strcasecmp(typeInput, "double")) {
datatype = REDUCE_DOUBLE;
} else if (strcasecmp(typeInput, "int")) {
printf("Type %s is not recognized. Using default type int.\n\n",
typeInput);
if (0 != typeInput) {
if (!strcasecmp(typeInput, "float")) {
datatype = REDUCE_FLOAT;
}
else if (!strcasecmp(typeInput, "double")) {
datatype = REDUCE_DOUBLE;
}
else if (strcasecmp(typeInput, "int")) {
printf("Type %s is not recognized. Using default type int.\n\n", typeInput);
}
}
}
cudaDeviceProp deviceProp;
int dev;
cudaDeviceProp deviceProp;
int dev;
dev = findCudaDevice(argc, (const char **)argv);
dev = findCudaDevice(argc, (const char **)argv);
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev));
checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev));
printf("Using Device %d: %s\n\n", dev, deviceProp.name);
checkCudaErrors(cudaSetDevice(dev));
printf("Using Device %d: %s\n\n", dev, deviceProp.name);
checkCudaErrors(cudaSetDevice(dev));
printf("Reducing array of type %s\n\n", getReduceTypeString(datatype));
printf("Reducing array of type %s\n\n", getReduceTypeString(datatype));
bool bResult = false;
bool bResult = false;
switch (datatype) {
switch (datatype) {
default:
case REDUCE_INT:
bResult = runTest<int>(argc, argv, datatype);
break;
bResult = runTest<int>(argc, argv, datatype);
break;
case REDUCE_FLOAT:
bResult = runTest<float>(argc, argv, datatype);
break;
bResult = runTest<float>(argc, argv, datatype);
break;
case REDUCE_DOUBLE:
bResult = runTest<double>(argc, argv, datatype);
break;
}
bResult = runTest<double>(argc, argv, datatype);
break;
}
printf(bResult ? "Test passed\n" : "Test failed!\n");
printf(bResult ? "Test passed\n" : "Test failed!\n");
}
////////////////////////////////////////////////////////////////////////////////
@@ -162,29 +164,30 @@ int main(int argc, char **argv) {
//! @param data pointer to input data
//! @param size number of input data elements
////////////////////////////////////////////////////////////////////////////////
template <class T>
T reduceCPU(T *data, int size) {
T sum = data[0];
T c = (T)0.0;
template <class T> T reduceCPU(T *data, int size)
{
T sum = data[0];
T c = (T)0.0;
for (int i = 1; i < size; i++) {
T y = data[i] - c;
T t = sum + y;
c = (t - sum) - y;
sum = t;
}
for (int i = 1; i < size; i++) {
T y = data[i] - c;
T t = sum + y;
c = (t - sum) - y;
sum = t;
}
return sum;
return sum;
}
unsigned int nextPow2(unsigned int x) {
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return ++x;
unsigned int nextPow2(unsigned int x)
{
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return ++x;
}
#ifndef MIN
@@ -198,40 +201,42 @@ unsigned int nextPow2(unsigned int x) {
// n. For kernel 6, we observe the maximum specified number of blocks, because
// each thread in that kernel can process a variable number of elements.
////////////////////////////////////////////////////////////////////////////////
void getNumBlocksAndThreads(int whichKernel, int n, int maxBlocks,
int maxThreads, int &blocks, int &threads) {
// get device capability, to avoid block/grid size exceed the upper bound
cudaDeviceProp prop;
int device;
checkCudaErrors(cudaGetDevice(&device));
checkCudaErrors(cudaGetDeviceProperties(&prop, device));
void getNumBlocksAndThreads(int whichKernel, int n, int maxBlocks, int maxThreads, int &blocks, int &threads)
{
// get device capability, to avoid block/grid size exceed the upper bound
cudaDeviceProp prop;
int device;
checkCudaErrors(cudaGetDevice(&device));
checkCudaErrors(cudaGetDeviceProperties(&prop, device));
if (whichKernel < 3) {
threads = (n < maxThreads) ? nextPow2(n) : maxThreads;
blocks = (n + threads - 1) / threads;
} else {
threads = (n < maxThreads * 2) ? nextPow2((n + 1) / 2) : maxThreads;
blocks = (n + (threads * 2 - 1)) / (threads * 2);
}
if (whichKernel < 3) {
threads = (n < maxThreads) ? nextPow2(n) : maxThreads;
blocks = (n + threads - 1) / threads;
}
else {
threads = (n < maxThreads * 2) ? nextPow2((n + 1) / 2) : maxThreads;
blocks = (n + (threads * 2 - 1)) / (threads * 2);
}
if ((float)threads * blocks >
(float)prop.maxGridSize[0] * prop.maxThreadsPerBlock) {
printf("n is too large, please choose a smaller number!\n");
}
if ((float)threads * blocks > (float)prop.maxGridSize[0] * prop.maxThreadsPerBlock) {
printf("n is too large, please choose a smaller number!\n");
}
if (blocks > prop.maxGridSize[0]) {
printf(
"Grid size <%d> exceeds the device capability <%d>, set block size as "
"%d (original %d)\n",
blocks, prop.maxGridSize[0], threads * 2, threads);
if (blocks > prop.maxGridSize[0]) {
printf("Grid size <%d> exceeds the device capability <%d>, set block size as "
"%d (original %d)\n",
blocks,
prop.maxGridSize[0],
threads * 2,
threads);
blocks /= 2;
threads *= 2;
}
blocks /= 2;
threads *= 2;
}
if (whichKernel >= 6) {
blocks = MIN(maxBlocks, blocks);
}
if (whichKernel >= 6) {
blocks = MIN(maxBlocks, blocks);
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -239,85 +244,90 @@ void getNumBlocksAndThreads(int whichKernel, int n, int maxBlocks,
// measures the average reduction time.
////////////////////////////////////////////////////////////////////////////////
template <class T>
T benchmarkReduce(int n, int numThreads, int numBlocks, int maxThreads,
int maxBlocks, int whichKernel, int testIterations,
bool cpuFinalReduction, int cpuFinalThreshold,
StopWatchInterface *timer, T *h_odata, T *d_idata,
T *d_odata) {
T gpu_result = 0;
bool needReadBack = true;
T benchmarkReduce(int n,
int numThreads,
int numBlocks,
int maxThreads,
int maxBlocks,
int whichKernel,
int testIterations,
bool cpuFinalReduction,
int cpuFinalThreshold,
StopWatchInterface *timer,
T *h_odata,
T *d_idata,
T *d_odata)
{
T gpu_result = 0;
bool needReadBack = true;
T *d_intermediateSums;
checkCudaErrors(
cudaMalloc((void **)&d_intermediateSums, sizeof(T) * numBlocks));
T *d_intermediateSums;
checkCudaErrors(cudaMalloc((void **)&d_intermediateSums, sizeof(T) * numBlocks));
for (int i = 0; i < testIterations; ++i) {
gpu_result = 0;
for (int i = 0; i < testIterations; ++i) {
gpu_result = 0;
cudaDeviceSynchronize();
sdkStartTimer(&timer);
cudaDeviceSynchronize();
sdkStartTimer(&timer);
// execute the kernel
reduce<T>(n, numThreads, numBlocks, whichKernel, d_idata, d_odata);
// execute the kernel
reduce<T>(n, numThreads, numBlocks, whichKernel, d_idata, d_odata);
// check if kernel execution generated an error
getLastCudaError("Kernel execution failed");
// check if kernel execution generated an error
getLastCudaError("Kernel execution failed");
if (cpuFinalReduction) {
// sum partial sums from each block on CPU
// copy result from device to host
checkCudaErrors(cudaMemcpy(h_odata, d_odata, numBlocks * sizeof(T),
cudaMemcpyDeviceToHost));
if (cpuFinalReduction) {
// sum partial sums from each block on CPU
// copy result from device to host
checkCudaErrors(cudaMemcpy(h_odata, d_odata, numBlocks * sizeof(T), cudaMemcpyDeviceToHost));
for (int i = 0; i < numBlocks; i++) {
gpu_result += h_odata[i];
}
for (int i = 0; i < numBlocks; i++) {
gpu_result += h_odata[i];
}
needReadBack = false;
} else {
// sum partial block sums on GPU
int s = numBlocks;
int kernel = whichKernel;
while (s > cpuFinalThreshold) {
int threads = 0, blocks = 0;
getNumBlocksAndThreads(kernel, s, maxBlocks, maxThreads, blocks,
threads);
checkCudaErrors(cudaMemcpy(d_intermediateSums, d_odata, s * sizeof(T),
cudaMemcpyDeviceToDevice));
reduce<T>(s, threads, blocks, kernel, d_intermediateSums, d_odata);
if (kernel < 3) {
s = (s + threads - 1) / threads;
} else {
s = (s + (threads * 2 - 1)) / (threads * 2);
needReadBack = false;
}
}
else {
// sum partial block sums on GPU
int s = numBlocks;
int kernel = whichKernel;
if (s > 1) {
// copy result from device to host
checkCudaErrors(cudaMemcpy(h_odata, d_odata, s * sizeof(T),
cudaMemcpyDeviceToHost));
while (s > cpuFinalThreshold) {
int threads = 0, blocks = 0;
getNumBlocksAndThreads(kernel, s, maxBlocks, maxThreads, blocks, threads);
checkCudaErrors(cudaMemcpy(d_intermediateSums, d_odata, s * sizeof(T), cudaMemcpyDeviceToDevice));
reduce<T>(s, threads, blocks, kernel, d_intermediateSums, d_odata);
for (int i = 0; i < s; i++) {
gpu_result += h_odata[i];
if (kernel < 3) {
s = (s + threads - 1) / threads;
}
else {
s = (s + (threads * 2 - 1)) / (threads * 2);
}
}
if (s > 1) {
// copy result from device to host
checkCudaErrors(cudaMemcpy(h_odata, d_odata, s * sizeof(T), cudaMemcpyDeviceToHost));
for (int i = 0; i < s; i++) {
gpu_result += h_odata[i];
}
needReadBack = false;
}
}
needReadBack = false;
}
cudaDeviceSynchronize();
sdkStopTimer(&timer);
}
cudaDeviceSynchronize();
sdkStopTimer(&timer);
}
if (needReadBack) {
// copy final sum from device to host
checkCudaErrors(
cudaMemcpy(&gpu_result, d_odata, sizeof(T), cudaMemcpyDeviceToHost));
}
checkCudaErrors(cudaFree(d_intermediateSums));
return gpu_result;
if (needReadBack) {
// copy final sum from device to host
checkCudaErrors(cudaMemcpy(&gpu_result, d_odata, sizeof(T), cudaMemcpyDeviceToHost));
}
checkCudaErrors(cudaFree(d_intermediateSums));
return gpu_result;
}
////////////////////////////////////////////////////////////////////////////////
@@ -326,222 +336,91 @@ T benchmarkReduce(int n, int numThreads, int numBlocks, int maxThreads,
// for generating a "shmoo" plot showing the performance for each kernel
// variation over a wide range of input sizes.
////////////////////////////////////////////////////////////////////////////////
template <class T>
void shmoo(int minN, int maxN, int maxThreads, int maxBlocks,
ReduceType datatype) {
// create random input data on CPU
unsigned int bytes = maxN * sizeof(T);
T *h_idata = (T *)malloc(bytes);
for (int i = 0; i < maxN; i++) {
// Keep the numbers small so we don't get truncation error in the sum
if (datatype == REDUCE_INT) {
h_idata[i] = (T)(rand() & 0xFF);
} else {
h_idata[i] = (rand() & 0xFF) / (T)RAND_MAX;
}
}
int maxNumBlocks = MIN(maxN / maxThreads, MAX_BLOCK_DIM_SIZE);
// allocate mem for the result on host side
T *h_odata = (T *)malloc(maxNumBlocks * sizeof(T));
// allocate device memory and data
T *d_idata = NULL;
T *d_odata = NULL;
checkCudaErrors(cudaMalloc((void **)&d_idata, bytes));
checkCudaErrors(cudaMalloc((void **)&d_odata, maxNumBlocks * sizeof(T)));
// copy data directly to device memory
checkCudaErrors(cudaMemcpy(d_idata, h_idata, bytes, cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(d_odata, h_idata, maxNumBlocks * sizeof(T),
cudaMemcpyHostToDevice));
// warm-up
for (int kernel = 0; kernel < 8; kernel++) {
reduce<T>(maxN, maxThreads, maxNumBlocks, kernel, d_idata, d_odata);
}
int testIterations = 100;
StopWatchInterface *timer = 0;
sdkCreateTimer(&timer);
// print headers
printf(
"Time in milliseconds for various numbers of elements for each "
"kernel\n\n\n");
printf("Kernel");
for (int i = minN; i <= maxN; i *= 2) {
printf(", %d", i);
}
for (int kernel = 0; kernel < 8; kernel++) {
printf("\n%d", kernel);
for (int i = minN; i <= maxN; i *= 2) {
sdkResetTimer(&timer);
int numBlocks = 0;
int numThreads = 0;
getNumBlocksAndThreads(kernel, i, maxBlocks, maxThreads, numBlocks,
numThreads);
float reduceTime;
if (numBlocks <= MAX_BLOCK_DIM_SIZE) {
benchmarkReduce(i, numThreads, numBlocks, maxThreads, maxBlocks, kernel,
testIterations, false, 1, timer, h_odata, d_idata,
d_odata);
reduceTime = sdkGetAverageTimerValue(&timer);
} else {
reduceTime = -1.0;
}
printf(", %.5f", reduceTime);
}
}
// cleanup
sdkDeleteTimer(&timer);
free(h_idata);
free(h_odata);
checkCudaErrors(cudaFree(d_idata));
checkCudaErrors(cudaFree(d_odata));
}
////////////////////////////////////////////////////////////////////////////////
// The main function which runs the reduction test.
////////////////////////////////////////////////////////////////////////////////
template <class T>
bool runTest(int argc, char **argv, ReduceType datatype) {
int size = 1 << 24; // number of elements to reduce
int maxThreads = 256; // number of threads per block
int whichKernel = 7;
int maxBlocks = 64;
bool cpuFinalReduction = false;
int cpuFinalThreshold = 1;
if (checkCmdLineFlag(argc, (const char **)argv, "n")) {
size = getCmdLineArgumentInt(argc, (const char **)argv, "n");
}
if (checkCmdLineFlag(argc, (const char **)argv, "threads")) {
maxThreads = getCmdLineArgumentInt(argc, (const char **)argv, "threads");
}
if (checkCmdLineFlag(argc, (const char **)argv, "kernel")) {
whichKernel = getCmdLineArgumentInt(argc, (const char **)argv, "kernel");
}
if (checkCmdLineFlag(argc, (const char **)argv, "maxblocks")) {
maxBlocks = getCmdLineArgumentInt(argc, (const char **)argv, "maxblocks");
}
printf("%d elements\n", size);
printf("%d threads (max)\n", maxThreads);
cpuFinalReduction = checkCmdLineFlag(argc, (const char **)argv, "cpufinal");
if (checkCmdLineFlag(argc, (const char **)argv, "cputhresh")) {
cpuFinalThreshold =
getCmdLineArgumentInt(argc, (const char **)argv, "cputhresh");
}
bool runShmoo = checkCmdLineFlag(argc, (const char **)argv, "shmoo");
if (runShmoo) {
shmoo<T>(1, 33554432, maxThreads, maxBlocks, datatype);
} else {
template <class T> void shmoo(int minN, int maxN, int maxThreads, int maxBlocks, ReduceType datatype)
{
// create random input data on CPU
unsigned int bytes = size * sizeof(T);
unsigned int bytes = maxN * sizeof(T);
T *h_idata = (T *)malloc(bytes);
for (int i = 0; i < size; i++) {
// Keep the numbers small so we don't get truncation error in the sum
if (datatype == REDUCE_INT) {
h_idata[i] = (T)(rand() & 0xFF);
} else {
h_idata[i] = (rand() & 0xFF) / (T)RAND_MAX;
}
for (int i = 0; i < maxN; i++) {
// Keep the numbers small so we don't get truncation error in the sum
if (datatype == REDUCE_INT) {
h_idata[i] = (T)(rand() & 0xFF);
}
else {
h_idata[i] = (rand() & 0xFF) / (T)RAND_MAX;
}
}
int numBlocks = 0;
int numThreads = 0;
getNumBlocksAndThreads(whichKernel, size, maxBlocks, maxThreads, numBlocks,
numThreads);
if (numBlocks == 1) {
cpuFinalThreshold = 1;
}
int maxNumBlocks = MIN(maxN / maxThreads, MAX_BLOCK_DIM_SIZE);
// allocate mem for the result on host side
T *h_odata = (T *)malloc(numBlocks * sizeof(T));
printf("%d blocks\n\n", numBlocks);
T *h_odata = (T *)malloc(maxNumBlocks * sizeof(T));
// allocate device memory and data
T *d_idata = NULL;
T *d_odata = NULL;
checkCudaErrors(cudaMalloc((void **)&d_idata, bytes));
checkCudaErrors(cudaMalloc((void **)&d_odata, numBlocks * sizeof(T)));
checkCudaErrors(cudaMalloc((void **)&d_odata, maxNumBlocks * sizeof(T)));
// copy data directly to device memory
checkCudaErrors(
cudaMemcpy(d_idata, h_idata, bytes, cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(d_odata, h_idata, numBlocks * sizeof(T),
cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(d_idata, h_idata, bytes, cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(d_odata, h_idata, maxNumBlocks * sizeof(T), cudaMemcpyHostToDevice));
// warm-up
reduce<T>(size, numThreads, numBlocks, whichKernel, d_idata, d_odata);
for (int kernel = 0; kernel < 8; kernel++) {
reduce<T>(maxN, maxThreads, maxNumBlocks, kernel, d_idata, d_odata);
}
int testIterations = 100;
StopWatchInterface *timer = 0;
sdkCreateTimer(&timer);
T gpu_result = 0;
// print headers
printf("Time in milliseconds for various numbers of elements for each "
"kernel\n\n\n");
printf("Kernel");
gpu_result =
benchmarkReduce<T>(size, numThreads, numBlocks, maxThreads, maxBlocks,
whichKernel, testIterations, cpuFinalReduction,
cpuFinalThreshold, timer, h_odata, d_idata, d_odata);
for (int i = minN; i <= maxN; i *= 2) {
printf(", %d", i);
}
double reduceTime = sdkGetAverageTimerValue(&timer) * 1e-3;
printf(
"Reduction, Throughput = %.4f GB/s, Time = %.5f s, Size = %u Elements, "
"NumDevsUsed = %d, Workgroup = %u\n",
1.0e-9 * ((double)bytes) / reduceTime, reduceTime, size, 1, numThreads);
for (int kernel = 0; kernel < 8; kernel++) {
printf("\n%d", kernel);
// compute reference solution
T cpu_result = reduceCPU<T>(h_idata, size);
for (int i = minN; i <= maxN; i *= 2) {
sdkResetTimer(&timer);
int numBlocks = 0;
int numThreads = 0;
getNumBlocksAndThreads(kernel, i, maxBlocks, maxThreads, numBlocks, numThreads);
int precision = 0;
double threshold = 0;
double diff = 0;
float reduceTime;
if (datatype == REDUCE_INT) {
printf("\nGPU result = %d\n", (int)gpu_result);
printf("CPU result = %d\n\n", (int)cpu_result);
} else {
if (datatype == REDUCE_FLOAT) {
precision = 8;
threshold = 1e-8 * size;
} else {
precision = 12;
threshold = 1e-12 * size;
}
if (numBlocks <= MAX_BLOCK_DIM_SIZE) {
benchmarkReduce(i,
numThreads,
numBlocks,
maxThreads,
maxBlocks,
kernel,
testIterations,
false,
1,
timer,
h_odata,
d_idata,
d_odata);
reduceTime = sdkGetAverageTimerValue(&timer);
}
else {
reduceTime = -1.0;
}
printf("\nGPU result = %.*f\n", precision, (double)gpu_result);
printf("CPU result = %.*f\n\n", precision, (double)cpu_result);
diff = fabs((double)gpu_result - (double)cpu_result);
printf(", %.5f", reduceTime);
}
}
// cleanup
@@ -551,13 +430,165 @@ bool runTest(int argc, char **argv, ReduceType datatype) {
checkCudaErrors(cudaFree(d_idata));
checkCudaErrors(cudaFree(d_odata));
if (datatype == REDUCE_INT) {
return (gpu_result == cpu_result);
} else {
return (diff < threshold);
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// The main function which runs the reduction test.
////////////////////////////////////////////////////////////////////////////////
template <class T> bool runTest(int argc, char **argv, ReduceType datatype)
{
int size = 1 << 24; // number of elements to reduce
int maxThreads = 256; // number of threads per block
int whichKernel = 7;
int maxBlocks = 64;
bool cpuFinalReduction = false;
int cpuFinalThreshold = 1;
if (checkCmdLineFlag(argc, (const char **)argv, "n")) {
size = getCmdLineArgumentInt(argc, (const char **)argv, "n");
}
if (checkCmdLineFlag(argc, (const char **)argv, "threads")) {
maxThreads = getCmdLineArgumentInt(argc, (const char **)argv, "threads");
}
if (checkCmdLineFlag(argc, (const char **)argv, "kernel")) {
whichKernel = getCmdLineArgumentInt(argc, (const char **)argv, "kernel");
}
if (checkCmdLineFlag(argc, (const char **)argv, "maxblocks")) {
maxBlocks = getCmdLineArgumentInt(argc, (const char **)argv, "maxblocks");
}
printf("%d elements\n", size);
printf("%d threads (max)\n", maxThreads);
cpuFinalReduction = checkCmdLineFlag(argc, (const char **)argv, "cpufinal");
if (checkCmdLineFlag(argc, (const char **)argv, "cputhresh")) {
cpuFinalThreshold = getCmdLineArgumentInt(argc, (const char **)argv, "cputhresh");
}
bool runShmoo = checkCmdLineFlag(argc, (const char **)argv, "shmoo");
if (runShmoo) {
shmoo<T>(1, 33554432, maxThreads, maxBlocks, datatype);
}
else {
// create random input data on CPU
unsigned int bytes = size * sizeof(T);
T *h_idata = (T *)malloc(bytes);
for (int i = 0; i < size; i++) {
// Keep the numbers small so we don't get truncation error in the sum
if (datatype == REDUCE_INT) {
h_idata[i] = (T)(rand() & 0xFF);
}
else {
h_idata[i] = (rand() & 0xFF) / (T)RAND_MAX;
}
}
int numBlocks = 0;
int numThreads = 0;
getNumBlocksAndThreads(whichKernel, size, maxBlocks, maxThreads, numBlocks, numThreads);
if (numBlocks == 1) {
cpuFinalThreshold = 1;
}
// allocate mem for the result on host side
T *h_odata = (T *)malloc(numBlocks * sizeof(T));
printf("%d blocks\n\n", numBlocks);
// allocate device memory and data
T *d_idata = NULL;
T *d_odata = NULL;
checkCudaErrors(cudaMalloc((void **)&d_idata, bytes));
checkCudaErrors(cudaMalloc((void **)&d_odata, numBlocks * sizeof(T)));
// copy data directly to device memory
checkCudaErrors(cudaMemcpy(d_idata, h_idata, bytes, cudaMemcpyHostToDevice));
checkCudaErrors(cudaMemcpy(d_odata, h_idata, numBlocks * sizeof(T), cudaMemcpyHostToDevice));
// warm-up
reduce<T>(size, numThreads, numBlocks, whichKernel, d_idata, d_odata);
int testIterations = 100;
StopWatchInterface *timer = 0;
sdkCreateTimer(&timer);
T gpu_result = 0;
gpu_result = benchmarkReduce<T>(size,
numThreads,
numBlocks,
maxThreads,
maxBlocks,
whichKernel,
testIterations,
cpuFinalReduction,
cpuFinalThreshold,
timer,
h_odata,
d_idata,
d_odata);
double reduceTime = sdkGetAverageTimerValue(&timer) * 1e-3;
printf("Reduction, Throughput = %.4f GB/s, Time = %.5f s, Size = %u Elements, "
"NumDevsUsed = %d, Workgroup = %u\n",
1.0e-9 * ((double)bytes) / reduceTime,
reduceTime,
size,
1,
numThreads);
// compute reference solution
T cpu_result = reduceCPU<T>(h_idata, size);
int precision = 0;
double threshold = 0;
double diff = 0;
if (datatype == REDUCE_INT) {
printf("\nGPU result = %d\n", (int)gpu_result);
printf("CPU result = %d\n\n", (int)cpu_result);
}
else {
if (datatype == REDUCE_FLOAT) {
precision = 8;
threshold = 1e-8 * size;
}
else {
precision = 12;
threshold = 1e-12 * size;
}
printf("\nGPU result = %.*f\n", precision, (double)gpu_result);
printf("CPU result = %.*f\n\n", precision, (double)cpu_result);
diff = fabs((double)gpu_result - (double)cpu_result);
}
// cleanup
sdkDeleteTimer(&timer);
free(h_idata);
free(h_odata);
checkCudaErrors(cudaFree(d_idata));
checkCudaErrors(cudaFree(d_odata));
if (datatype == REDUCE_INT) {
return (gpu_result == cpu_result);
}
else {
return (diff < threshold);
}
}
return true;
}

View File

@@ -29,8 +29,6 @@
#ifndef __REDUCTION_H__
#define __REDUCTION_H__
template <class T>
void reduce(int size, int threads, int blocks,
int whichKernel, T *d_idata, T *d_odata);
template <class T> void reduce(int size, int threads, int blocks, int whichKernel, T *d_idata, T *d_odata);
#endif

File diff suppressed because it is too large Load Diff