mirror of
https://github.com/NVIDIA/cuda-samples.git
synced 2026-10-26 06:38:16 +08:00
Apply consistent code formatting across the repo. Add clang-format and pre-commit hooks.
This commit is contained in:
@@ -38,20 +38,18 @@
|
||||
* Victor Podlozhnyuk (vpodlozhnyuk@nvidia.com)
|
||||
*/
|
||||
|
||||
#include <helper_cuda.h>
|
||||
#include <helper_functions.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <helper_functions.h>
|
||||
#include <helper_cuda.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Reference CPU FWT
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" void fwtCPU(float *h_Output, float *h_Input, int log2N);
|
||||
extern "C" void slowWTcpu(float *h_Output, float *h_Input, int log2N);
|
||||
extern "C" void dyadicConvolutionCPU(float *h_Result, float *h_Data,
|
||||
float *h_Kernel, int log2dataN,
|
||||
int log2kernelN);
|
||||
extern "C" void dyadicConvolutionCPU(float *h_Result, float *h_Data, float *h_Kernel, int log2dataN, int log2kernelN);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GPU FWT
|
||||
@@ -62,12 +60,12 @@ extern "C" void dyadicConvolutionCPU(float *h_Result, float *h_Data,
|
||||
// Data configuration
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const int log2Kernel = 7;
|
||||
const int log2Data = 23;
|
||||
const int log2Data = 23;
|
||||
|
||||
const int dataN = 1 << log2Data;
|
||||
const int dataN = 1 << log2Data;
|
||||
const int kernelN = 1 << log2Kernel;
|
||||
|
||||
const int DATA_SIZE = dataN * sizeof(float);
|
||||
const int DATA_SIZE = dataN * sizeof(float);
|
||||
const int KERNEL_SIZE = kernelN * sizeof(float);
|
||||
|
||||
const double NOPS = 3.0 * (double)dataN * (double)log2Data / 2.0;
|
||||
@@ -75,95 +73,92 @@ const double NOPS = 3.0 * (double)dataN * (double)log2Data / 2.0;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char *argv[]) {
|
||||
float *h_Data, *h_Kernel, *h_ResultCPU, *h_ResultGPU;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
float *h_Data, *h_Kernel, *h_ResultCPU, *h_ResultGPU;
|
||||
|
||||
float *d_Data, *d_Kernel;
|
||||
float *d_Data, *d_Kernel;
|
||||
|
||||
double delta, ref, sum_delta2, sum_ref2, L2norm, gpuTime;
|
||||
double delta, ref, sum_delta2, sum_ref2, L2norm, gpuTime;
|
||||
|
||||
StopWatchInterface *hTimer = NULL;
|
||||
int i;
|
||||
StopWatchInterface *hTimer = NULL;
|
||||
int i;
|
||||
|
||||
printf("%s Starting...\n\n", argv[0]);
|
||||
printf("%s Starting...\n\n", argv[0]);
|
||||
|
||||
// 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("Initializing data...\n");
|
||||
printf("...allocating CPU memory\n");
|
||||
h_Kernel = (float *)malloc(KERNEL_SIZE);
|
||||
h_Data = (float *)malloc(DATA_SIZE);
|
||||
h_ResultCPU = (float *)malloc(DATA_SIZE);
|
||||
h_ResultGPU = (float *)malloc(DATA_SIZE);
|
||||
printf("...allocating GPU memory\n");
|
||||
checkCudaErrors(cudaMalloc((void **)&d_Kernel, DATA_SIZE));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_Data, DATA_SIZE));
|
||||
printf("Initializing data...\n");
|
||||
printf("...allocating CPU memory\n");
|
||||
h_Kernel = (float *)malloc(KERNEL_SIZE);
|
||||
h_Data = (float *)malloc(DATA_SIZE);
|
||||
h_ResultCPU = (float *)malloc(DATA_SIZE);
|
||||
h_ResultGPU = (float *)malloc(DATA_SIZE);
|
||||
printf("...allocating GPU memory\n");
|
||||
checkCudaErrors(cudaMalloc((void **)&d_Kernel, DATA_SIZE));
|
||||
checkCudaErrors(cudaMalloc((void **)&d_Data, DATA_SIZE));
|
||||
|
||||
printf("...generating data\n");
|
||||
printf("Data length: %i; kernel length: %i\n", dataN, kernelN);
|
||||
srand(2007);
|
||||
printf("...generating data\n");
|
||||
printf("Data length: %i; kernel length: %i\n", dataN, kernelN);
|
||||
srand(2007);
|
||||
|
||||
for (i = 0; i < kernelN; i++) {
|
||||
h_Kernel[i] = (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
for (i = 0; i < kernelN; i++) {
|
||||
h_Kernel[i] = (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
|
||||
for (i = 0; i < dataN; i++) {
|
||||
h_Data[i] = (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
for (i = 0; i < dataN; i++) {
|
||||
h_Data[i] = (float)rand() / (float)RAND_MAX;
|
||||
}
|
||||
|
||||
checkCudaErrors(cudaMemset(d_Kernel, 0, DATA_SIZE));
|
||||
checkCudaErrors(
|
||||
cudaMemcpy(d_Kernel, h_Kernel, KERNEL_SIZE, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(
|
||||
cudaMemcpy(d_Data, h_Data, DATA_SIZE, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemset(d_Kernel, 0, DATA_SIZE));
|
||||
checkCudaErrors(cudaMemcpy(d_Kernel, h_Kernel, KERNEL_SIZE, cudaMemcpyHostToDevice));
|
||||
checkCudaErrors(cudaMemcpy(d_Data, h_Data, DATA_SIZE, cudaMemcpyHostToDevice));
|
||||
|
||||
printf("Running GPU dyadic convolution using Fast Walsh Transform...\n");
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
sdkResetTimer(&hTimer);
|
||||
sdkStartTimer(&hTimer);
|
||||
fwtBatchGPU(d_Data, 1, log2Data);
|
||||
fwtBatchGPU(d_Kernel, 1, log2Data);
|
||||
modulateGPU(d_Data, d_Kernel, dataN);
|
||||
fwtBatchGPU(d_Data, 1, log2Data);
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
sdkStopTimer(&hTimer);
|
||||
gpuTime = sdkGetTimerValue(&hTimer);
|
||||
printf("GPU time: %f ms; GOP/s: %f\n", gpuTime,
|
||||
NOPS / (gpuTime * 0.001 * 1E+9));
|
||||
printf("Running GPU dyadic convolution using Fast Walsh Transform...\n");
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
sdkResetTimer(&hTimer);
|
||||
sdkStartTimer(&hTimer);
|
||||
fwtBatchGPU(d_Data, 1, log2Data);
|
||||
fwtBatchGPU(d_Kernel, 1, log2Data);
|
||||
modulateGPU(d_Data, d_Kernel, dataN);
|
||||
fwtBatchGPU(d_Data, 1, log2Data);
|
||||
checkCudaErrors(cudaDeviceSynchronize());
|
||||
sdkStopTimer(&hTimer);
|
||||
gpuTime = sdkGetTimerValue(&hTimer);
|
||||
printf("GPU time: %f ms; GOP/s: %f\n", gpuTime, NOPS / (gpuTime * 0.001 * 1E+9));
|
||||
|
||||
printf("Reading back GPU results...\n");
|
||||
checkCudaErrors(
|
||||
cudaMemcpy(h_ResultGPU, d_Data, DATA_SIZE, cudaMemcpyDeviceToHost));
|
||||
printf("Reading back GPU results...\n");
|
||||
checkCudaErrors(cudaMemcpy(h_ResultGPU, d_Data, DATA_SIZE, cudaMemcpyDeviceToHost));
|
||||
|
||||
printf("Running straightforward CPU dyadic convolution...\n");
|
||||
dyadicConvolutionCPU(h_ResultCPU, h_Data, h_Kernel, log2Data, log2Kernel);
|
||||
printf("Running straightforward CPU dyadic convolution...\n");
|
||||
dyadicConvolutionCPU(h_ResultCPU, h_Data, h_Kernel, log2Data, log2Kernel);
|
||||
|
||||
printf("Comparing the results...\n");
|
||||
sum_delta2 = 0;
|
||||
sum_ref2 = 0;
|
||||
printf("Comparing the results...\n");
|
||||
sum_delta2 = 0;
|
||||
sum_ref2 = 0;
|
||||
|
||||
for (i = 0; i < dataN; i++) {
|
||||
delta = h_ResultCPU[i] - h_ResultGPU[i];
|
||||
ref = h_ResultCPU[i];
|
||||
sum_delta2 += delta * delta;
|
||||
sum_ref2 += ref * ref;
|
||||
}
|
||||
for (i = 0; i < dataN; i++) {
|
||||
delta = h_ResultCPU[i] - h_ResultGPU[i];
|
||||
ref = h_ResultCPU[i];
|
||||
sum_delta2 += delta * delta;
|
||||
sum_ref2 += ref * ref;
|
||||
}
|
||||
|
||||
L2norm = sqrt(sum_delta2 / sum_ref2);
|
||||
L2norm = sqrt(sum_delta2 / sum_ref2);
|
||||
|
||||
printf("Shutting down...\n");
|
||||
sdkDeleteTimer(&hTimer);
|
||||
checkCudaErrors(cudaFree(d_Data));
|
||||
checkCudaErrors(cudaFree(d_Kernel));
|
||||
free(h_ResultGPU);
|
||||
free(h_ResultCPU);
|
||||
free(h_Data);
|
||||
free(h_Kernel);
|
||||
printf("Shutting down...\n");
|
||||
sdkDeleteTimer(&hTimer);
|
||||
checkCudaErrors(cudaFree(d_Data));
|
||||
checkCudaErrors(cudaFree(d_Kernel));
|
||||
free(h_ResultGPU);
|
||||
free(h_ResultCPU);
|
||||
free(h_Data);
|
||||
free(h_Kernel);
|
||||
|
||||
printf("L2 norm: %E\n", L2norm);
|
||||
printf(L2norm < 1e-6 ? "Test passed\n" : "Test failed!\n");
|
||||
printf("L2 norm: %E\n", L2norm);
|
||||
printf(L2norm < 1e-6 ? "Test passed\n" : "Test failed!\n");
|
||||
}
|
||||
|
||||
@@ -28,68 +28,72 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CPU Fast Walsh Transform
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" void fwtCPU(float *h_Output, float *h_Input, int log2N) {
|
||||
const int N = 1 << log2N;
|
||||
extern "C" void fwtCPU(float *h_Output, float *h_Input, int log2N)
|
||||
{
|
||||
const int N = 1 << log2N;
|
||||
|
||||
for (int pos = 0; pos < N; pos++) h_Output[pos] = h_Input[pos];
|
||||
for (int pos = 0; pos < N; pos++)
|
||||
h_Output[pos] = h_Input[pos];
|
||||
|
||||
// Cycle through stages with different butterfly strides
|
||||
for (int stride = N / 2; stride >= 1; stride >>= 1) {
|
||||
// Cycle through subvectors of (2 * stride) elements
|
||||
for (int base = 0; base < N; base += 2 * stride)
|
||||
// Cycle through stages with different butterfly strides
|
||||
for (int stride = N / 2; stride >= 1; stride >>= 1) {
|
||||
// Cycle through subvectors of (2 * stride) elements
|
||||
for (int base = 0; base < N; base += 2 * stride)
|
||||
|
||||
// Butterfly index within subvector of (2 * stride) size
|
||||
for (int j = 0; j < stride; j++) {
|
||||
int i0 = base + j + 0;
|
||||
int i1 = base + j + stride;
|
||||
// Butterfly index within subvector of (2 * stride) size
|
||||
for (int j = 0; j < stride; j++) {
|
||||
int i0 = base + j + 0;
|
||||
int i1 = base + j + stride;
|
||||
|
||||
float T1 = h_Output[i0];
|
||||
float T2 = h_Output[i1];
|
||||
h_Output[i0] = T1 + T2;
|
||||
h_Output[i1] = T1 - T2;
|
||||
}
|
||||
}
|
||||
float T1 = h_Output[i0];
|
||||
float T2 = h_Output[i1];
|
||||
h_Output[i0] = T1 + T2;
|
||||
h_Output[i1] = T1 - T2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Straightforward Walsh Transform: used to test both CPU and GPU FWT
|
||||
// Slow. Uses doubles because of straightforward accumulation
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" void slowWTcpu(float *h_Output, float *h_Input, int log2N) {
|
||||
const int N = 1 << log2N;
|
||||
extern "C" void slowWTcpu(float *h_Output, float *h_Input, int log2N)
|
||||
{
|
||||
const int N = 1 << log2N;
|
||||
|
||||
for (int i = 0; i < N; i++) {
|
||||
double sum = 0;
|
||||
for (int i = 0; i < N; i++) {
|
||||
double sum = 0;
|
||||
|
||||
for (int j = 0; j < N; j++) {
|
||||
// Walsh-Hadamard quotient
|
||||
double q = 1.0;
|
||||
for (int j = 0; j < N; j++) {
|
||||
// Walsh-Hadamard quotient
|
||||
double q = 1.0;
|
||||
|
||||
for (int t = i & j; t != 0; t >>= 1)
|
||||
if (t & 1) q = -q;
|
||||
for (int t = i & j; t != 0; t >>= 1)
|
||||
if (t & 1)
|
||||
q = -q;
|
||||
|
||||
sum += q * h_Input[j];
|
||||
sum += q * h_Input[j];
|
||||
}
|
||||
|
||||
h_Output[i] = (float)sum;
|
||||
}
|
||||
|
||||
h_Output[i] = (float)sum;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Reference CPU dyadic convolution.
|
||||
// Extremely slow because of non-linear memory access patterns (cache thrashing)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
extern "C" void dyadicConvolutionCPU(float *h_Result, float *h_Data,
|
||||
float *h_Kernel, int log2dataN,
|
||||
int log2kernelN) {
|
||||
const int dataN = 1 << log2dataN;
|
||||
const int kernelN = 1 << log2kernelN;
|
||||
extern "C" void dyadicConvolutionCPU(float *h_Result, float *h_Data, float *h_Kernel, int log2dataN, int log2kernelN)
|
||||
{
|
||||
const int dataN = 1 << log2dataN;
|
||||
const int kernelN = 1 << log2kernelN;
|
||||
|
||||
for (int i = 0; i < dataN; i++) {
|
||||
double sum = 0;
|
||||
for (int i = 0; i < dataN; i++) {
|
||||
double sum = 0;
|
||||
|
||||
for (int j = 0; j < kernelN; j++) sum += h_Data[i ^ j] * h_Kernel[j];
|
||||
for (int j = 0; j < kernelN; j++)
|
||||
sum += h_Data[i ^ j] * h_Kernel[j];
|
||||
|
||||
h_Result[i] = (float)sum;
|
||||
}
|
||||
h_Result[i] = (float)sum;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,146 +40,148 @@ namespace cg = cooperative_groups;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#define ELEMENTARY_LOG2SIZE 11
|
||||
|
||||
__global__ void fwtBatch1Kernel(float *d_Output, float *d_Input, int log2N) {
|
||||
// Handle to thread block group
|
||||
cg::thread_block cta = cg::this_thread_block();
|
||||
const int N = 1 << log2N;
|
||||
const int base = blockIdx.x << log2N;
|
||||
__global__ void fwtBatch1Kernel(float *d_Output, float *d_Input, int log2N)
|
||||
{
|
||||
// Handle to thread block group
|
||||
cg::thread_block cta = cg::this_thread_block();
|
||||
const int N = 1 << log2N;
|
||||
const int base = blockIdx.x << log2N;
|
||||
|
||||
//(2 ** 11) * 4 bytes == 8KB -- maximum s_data[] size for G80
|
||||
extern __shared__ float s_data[];
|
||||
float *d_Src = d_Input + base;
|
||||
float *d_Dst = d_Output + base;
|
||||
//(2 ** 11) * 4 bytes == 8KB -- maximum s_data[] size for G80
|
||||
extern __shared__ float s_data[];
|
||||
float *d_Src = d_Input + base;
|
||||
float *d_Dst = d_Output + base;
|
||||
|
||||
for (int pos = threadIdx.x; pos < N; pos += blockDim.x) {
|
||||
s_data[pos] = d_Src[pos];
|
||||
}
|
||||
|
||||
// Main radix-4 stages
|
||||
const int pos = threadIdx.x;
|
||||
|
||||
for (int stride = N >> 2; stride > 0; stride >>= 2) {
|
||||
int lo = pos & (stride - 1);
|
||||
int i0 = ((pos - lo) << 2) + lo;
|
||||
int i1 = i0 + stride;
|
||||
int i2 = i1 + stride;
|
||||
int i3 = i2 + stride;
|
||||
|
||||
cg::sync(cta);
|
||||
float D0 = s_data[i0];
|
||||
float D1 = s_data[i1];
|
||||
float D2 = s_data[i2];
|
||||
float D3 = s_data[i3];
|
||||
|
||||
float T;
|
||||
T = D0;
|
||||
D0 = D0 + D2;
|
||||
D2 = T - D2;
|
||||
T = D1;
|
||||
D1 = D1 + D3;
|
||||
D3 = T - D3;
|
||||
T = D0;
|
||||
s_data[i0] = D0 + D1;
|
||||
s_data[i1] = T - D1;
|
||||
T = D2;
|
||||
s_data[i2] = D2 + D3;
|
||||
s_data[i3] = T - D3;
|
||||
}
|
||||
|
||||
// Do single radix-2 stage for odd power of two
|
||||
if (log2N & 1) {
|
||||
cg::sync(cta);
|
||||
|
||||
for (int pos = threadIdx.x; pos < N / 2; pos += blockDim.x) {
|
||||
int i0 = pos << 1;
|
||||
int i1 = i0 + 1;
|
||||
|
||||
float D0 = s_data[i0];
|
||||
float D1 = s_data[i1];
|
||||
s_data[i0] = D0 + D1;
|
||||
s_data[i1] = D0 - D1;
|
||||
for (int pos = threadIdx.x; pos < N; pos += blockDim.x) {
|
||||
s_data[pos] = d_Src[pos];
|
||||
}
|
||||
}
|
||||
|
||||
cg::sync(cta);
|
||||
// Main radix-4 stages
|
||||
const int pos = threadIdx.x;
|
||||
|
||||
for (int pos = threadIdx.x; pos < N; pos += blockDim.x) {
|
||||
d_Dst[pos] = s_data[pos];
|
||||
}
|
||||
for (int stride = N >> 2; stride > 0; stride >>= 2) {
|
||||
int lo = pos & (stride - 1);
|
||||
int i0 = ((pos - lo) << 2) + lo;
|
||||
int i1 = i0 + stride;
|
||||
int i2 = i1 + stride;
|
||||
int i3 = i2 + stride;
|
||||
|
||||
cg::sync(cta);
|
||||
float D0 = s_data[i0];
|
||||
float D1 = s_data[i1];
|
||||
float D2 = s_data[i2];
|
||||
float D3 = s_data[i3];
|
||||
|
||||
float T;
|
||||
T = D0;
|
||||
D0 = D0 + D2;
|
||||
D2 = T - D2;
|
||||
T = D1;
|
||||
D1 = D1 + D3;
|
||||
D3 = T - D3;
|
||||
T = D0;
|
||||
s_data[i0] = D0 + D1;
|
||||
s_data[i1] = T - D1;
|
||||
T = D2;
|
||||
s_data[i2] = D2 + D3;
|
||||
s_data[i3] = T - D3;
|
||||
}
|
||||
|
||||
// Do single radix-2 stage for odd power of two
|
||||
if (log2N & 1) {
|
||||
cg::sync(cta);
|
||||
|
||||
for (int pos = threadIdx.x; pos < N / 2; pos += blockDim.x) {
|
||||
int i0 = pos << 1;
|
||||
int i1 = i0 + 1;
|
||||
|
||||
float D0 = s_data[i0];
|
||||
float D1 = s_data[i1];
|
||||
s_data[i0] = D0 + D1;
|
||||
s_data[i1] = D0 - D1;
|
||||
}
|
||||
}
|
||||
|
||||
cg::sync(cta);
|
||||
|
||||
for (int pos = threadIdx.x; pos < N; pos += blockDim.x) {
|
||||
d_Dst[pos] = s_data[pos];
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Single in-global memory radix-4 Fast Walsh Transform pass
|
||||
// (for strides exceeding elementary vector size)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
__global__ void fwtBatch2Kernel(float *d_Output, float *d_Input, int stride) {
|
||||
const int pos = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int N = blockDim.x * gridDim.x * 4;
|
||||
__global__ void fwtBatch2Kernel(float *d_Output, float *d_Input, int stride)
|
||||
{
|
||||
const int pos = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
const int N = blockDim.x * gridDim.x * 4;
|
||||
|
||||
float *d_Src = d_Input + blockIdx.y * N;
|
||||
float *d_Dst = d_Output + blockIdx.y * N;
|
||||
float *d_Src = d_Input + blockIdx.y * N;
|
||||
float *d_Dst = d_Output + blockIdx.y * N;
|
||||
|
||||
int lo = pos & (stride - 1);
|
||||
int i0 = ((pos - lo) << 2) + lo;
|
||||
int i1 = i0 + stride;
|
||||
int i2 = i1 + stride;
|
||||
int i3 = i2 + stride;
|
||||
int lo = pos & (stride - 1);
|
||||
int i0 = ((pos - lo) << 2) + lo;
|
||||
int i1 = i0 + stride;
|
||||
int i2 = i1 + stride;
|
||||
int i3 = i2 + stride;
|
||||
|
||||
float D0 = d_Src[i0];
|
||||
float D1 = d_Src[i1];
|
||||
float D2 = d_Src[i2];
|
||||
float D3 = d_Src[i3];
|
||||
float D0 = d_Src[i0];
|
||||
float D1 = d_Src[i1];
|
||||
float D2 = d_Src[i2];
|
||||
float D3 = d_Src[i3];
|
||||
|
||||
float T;
|
||||
T = D0;
|
||||
D0 = D0 + D2;
|
||||
D2 = T - D2;
|
||||
T = D1;
|
||||
D1 = D1 + D3;
|
||||
D3 = T - D3;
|
||||
T = D0;
|
||||
d_Dst[i0] = D0 + D1;
|
||||
d_Dst[i1] = T - D1;
|
||||
T = D2;
|
||||
d_Dst[i2] = D2 + D3;
|
||||
d_Dst[i3] = T - D3;
|
||||
float T;
|
||||
T = D0;
|
||||
D0 = D0 + D2;
|
||||
D2 = T - D2;
|
||||
T = D1;
|
||||
D1 = D1 + D3;
|
||||
D3 = T - D3;
|
||||
T = D0;
|
||||
d_Dst[i0] = D0 + D1;
|
||||
d_Dst[i1] = T - D1;
|
||||
T = D2;
|
||||
d_Dst[i2] = D2 + D3;
|
||||
d_Dst[i3] = T - D3;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Put everything together: batched Fast Walsh Transform CPU front-end
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void fwtBatchGPU(float *d_Data, int M, int log2N) {
|
||||
const int THREAD_N = 256;
|
||||
void fwtBatchGPU(float *d_Data, int M, int log2N)
|
||||
{
|
||||
const int THREAD_N = 256;
|
||||
|
||||
int N = 1 << log2N;
|
||||
dim3 grid((1 << log2N) / (4 * THREAD_N), M, 1);
|
||||
int N = 1 << log2N;
|
||||
dim3 grid((1 << log2N) / (4 * THREAD_N), M, 1);
|
||||
|
||||
for (; log2N > ELEMENTARY_LOG2SIZE; log2N -= 2, N >>= 2, M <<= 2) {
|
||||
fwtBatch2Kernel<<<grid, THREAD_N>>>(d_Data, d_Data, N / 4);
|
||||
getLastCudaError("fwtBatch2Kernel() execution failed\n");
|
||||
}
|
||||
for (; log2N > ELEMENTARY_LOG2SIZE; log2N -= 2, N >>= 2, M <<= 2) {
|
||||
fwtBatch2Kernel<<<grid, THREAD_N>>>(d_Data, d_Data, N / 4);
|
||||
getLastCudaError("fwtBatch2Kernel() execution failed\n");
|
||||
}
|
||||
|
||||
fwtBatch1Kernel<<<M, N / 4, N * sizeof(float)>>>(d_Data, d_Data, log2N);
|
||||
getLastCudaError("fwtBatch1Kernel() execution failed\n");
|
||||
fwtBatch1Kernel<<<M, N / 4, N * sizeof(float)>>>(d_Data, d_Data, log2N);
|
||||
getLastCudaError("fwtBatch1Kernel() execution failed\n");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Modulate two arrays
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
__global__ void modulateKernel(float *d_A, float *d_B, int N) {
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int numThreads = blockDim.x * gridDim.x;
|
||||
float rcpN = 1.0f / (float)N;
|
||||
__global__ void modulateKernel(float *d_A, float *d_B, int N)
|
||||
{
|
||||
int tid = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int numThreads = blockDim.x * gridDim.x;
|
||||
float rcpN = 1.0f / (float)N;
|
||||
|
||||
for (int pos = tid; pos < N; pos += numThreads) {
|
||||
d_A[pos] *= d_B[pos] * rcpN;
|
||||
}
|
||||
for (int pos = tid; pos < N; pos += numThreads) {
|
||||
d_A[pos] *= d_B[pos] * rcpN;
|
||||
}
|
||||
}
|
||||
|
||||
// Interface to modulateKernel()
|
||||
void modulateGPU(float *d_A, float *d_B, int N) {
|
||||
modulateKernel<<<128, 256>>>(d_A, d_B, N);
|
||||
}
|
||||
void modulateGPU(float *d_A, float *d_B, int N) { modulateKernel<<<128, 256>>>(d_A, d_B, N); }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user