1+ /*
2+ * Copyright 1993-2014 NVIDIA Corporation. All rights reserved.
3+ *
4+ * Please refer to the NVIDIA end user license agreement (EULA) associated
5+ * with this source code for terms and conditions that govern your use of
6+ * this software. Any use, reproduction, disclosure, or distribution of
7+ * this software and related documentation outside the terms of the EULA
8+ * is strictly prohibited.
9+ *
10+ */
11+
12+ #include < stdlib.h>
13+ #include < stdio.h>
14+ #include < string.h>
15+ #include < math.h>
16+ #include < cuda_runtime.h>
17+ #include < cufft.h>
18+ #include < cufftXt.h>
19+
20+ #include " common.h"
21+
22+ #define TILE_DIM 32
23+ #define BLOCK_ROWS 8
24+
25+ // //////////////////////////////////////////////////////////////////////////////
26+ // Callback Implementations
27+ // //////////////////////////////////////////////////////////////////////////////
28+ __device__ cufftReal CB_ConvertInputR (void *dataIn, size_t offset, void *callerInfo, void *sharedPtr) {
29+ char element = ((char *)dataIn)[offset];
30+ return (cufftReal)((float )element/127 .0f );
31+ }
32+
33+ __device__ cufftCallbackLoadR d_loadCallbackPtr = CB_ConvertInputR;
34+
35+ __device__ void CB_ConvolveAndStoreTransposedC (void *dataOut, size_t offset, cufftComplex element, void *callerInfo, void *sharedPtr) {
36+ cufftComplex *filter = (cufftComplex*)callerInfo;
37+ size_t row = offset / COMPLEX_SIGNAL_SIZE ;
38+ size_t col = offset % COMPLEX_SIGNAL_SIZE ;
39+
40+ ((cufftComplex*)dataOut)[col * BATCH_SIZE + row] = ComplexMul (element, filter[col]);
41+ }
42+
43+ __device__ cufftCallbackStoreC d_storeCallbackPtr = CB_ConvolveAndStoreTransposedC;
44+
45+ // //////////////////////////////////////////////////////////////////////////////
46+ // Program main
47+ // //////////////////////////////////////////////////////////////////////////////
48+ int main (int argc, const char **argv)
49+ {
50+ struct cudaDeviceProp properties;
51+ int device = argc > 1 ? atoi (argv[1 ]) : 0 ;
52+
53+ checkCudaErrors (cudaGetDevice (&device));
54+ checkCudaErrors (cudaGetDeviceProperties (&properties, device));
55+ if ( !(properties.major >= 2 ) ) {
56+ printf (" This sample requires CUDA architecture SM2.0 or higher\n " );
57+ exit (EXIT_FAILURE );
58+ }
59+
60+ // Allocate and initialize memory
61+ printf (" Preparing input: %dx%d\n " , BATCH_SIZE , INPUT_SIGNAL_SIZE );
62+ char *_8bit_signal;
63+ cufftComplex *result, *filter;
64+
65+ checkCudaErrors (cudaMallocManaged (&_8bit_signal, sizeof (char ) * INPUT_SIGNAL_SIZE * BATCH_SIZE , cudaMemAttachGlobal));
66+ checkCudaErrors (cudaMallocManaged (&result, sizeof (cufftComplex) * COMPLEX_SIGNAL_SIZE * BATCH_SIZE , cudaMemAttachGlobal));
67+ checkCudaErrors (cudaMallocManaged (&filter, sizeof (cufftComplex) * COMPLEX_SIGNAL_SIZE , cudaMemAttachGlobal));
68+
69+ initInputs (_8bit_signal, filter);
70+
71+ // compute reference result for later verification
72+ printf (" Computing reference solution\n " );
73+ cufftComplex *reference = computeReference (_8bit_signal, filter);
74+
75+ printf (" Creating FFT plan\n " );
76+ cufftHandle fftPlan;
77+ size_t workSize;
78+
79+ checkCudaErrors (cufftCreate (&fftPlan));
80+ int signalSize = INPUT_SIGNAL_SIZE ;
81+ checkCudaErrors (cufftMakePlanMany (fftPlan, 1 , &signalSize, 0 ,0 ,0 ,0 ,0 ,0 , CUFFT_R2C , BATCH_SIZE , &workSize));
82+
83+ /*
84+ * Retrieve address of callback functions on the device
85+ */
86+ cufftCallbackLoadR h_loadCallbackPtr;
87+ cufftCallbackStoreC h_storeCallbackPtr;
88+ checkCudaErrors (cudaMemcpyFromSymbol (&h_loadCallbackPtr,
89+ d_loadCallbackPtr,
90+ sizeof (h_loadCallbackPtr)));
91+ checkCudaErrors (cudaMemcpyFromSymbol (&h_storeCallbackPtr,
92+ d_storeCallbackPtr,
93+ sizeof (h_storeCallbackPtr)));
94+
95+ // Now associate the callbacks with the plan.
96+ cufftResult status = cufftXtSetCallback (fftPlan,
97+ (void **)&h_loadCallbackPtr,
98+ CUFFT_CB_LD_REAL ,
99+ 0 );
100+ if (status == CUFFT_LICENSE_ERROR ) {
101+ printf (" This sample requires a valid license file.\n " );
102+ printf (" The file was either not found, out of date, or otherwise invalid.\n " );
103+ exit (EXIT_FAILURE );
104+ } else {
105+ checkCudaErrors (status);
106+ }
107+
108+ checkCudaErrors (cufftXtSetCallback (fftPlan,
109+ (void **)&h_storeCallbackPtr,
110+ CUFFT_CB_ST_COMPLEX ,
111+ (void **)&filter));
112+
113+ // create timers
114+ cudaEvent_t start, end;
115+ cudaEventCreate (&start);
116+ cudaEventCreate (&end);
117+ float elapsedTime;
118+
119+ printf (" Running %d iterations\n " , ITERATIONS );
120+ checkCudaErrors (cudaEventRecord (start, 0 ));
121+
122+ /*
123+ * The actual Computation
124+ */
125+
126+ for (int i = 0 ; i < ITERATIONS ; i++) {
127+ checkCudaErrors (cufftExecR2C (fftPlan, (cufftReal*)_8bit_signal, result));
128+ }
129+
130+ checkCudaErrors (cudaEventRecord (end, 0 ));
131+ checkCudaErrors (cudaEventSynchronize (end));
132+ checkCudaErrors (cudaEventElapsedTime (&elapsedTime, start, end));
133+ printf (" Time for the FFT: %fms\n " , elapsedTime);
134+
135+ // Verify correct result
136+ if (postprocess (reference, result, COMPLEX_SIGNAL_SIZE * BATCH_SIZE )) {
137+ printf (" Verification successful.\n " );
138+ } else {
139+ printf (" !!! Verification Failed !!!\n " );
140+ }
141+
142+ // Cleanup
143+ checkCudaErrors (cufftDestroy (fftPlan));
144+
145+ checkCudaErrors (cudaFree (_8bit_signal));
146+ checkCudaErrors (cudaFree (result));
147+ checkCudaErrors (cudaFree (filter));
148+ checkCudaErrors (cudaFree (reference));
149+
150+ // clean up driver state
151+ cudaDeviceReset ();
152+
153+ printf (" Done\n " );
154+
155+ return 0 ;
156+ }
0 commit comments