320 字
2 分钟
Hilbert 变换
Hilbert 变换
1、在GPU实现
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<cuda_runtime.h>#include <cufft.h>extern "C" { #include<rsf.h>}
__global__ void apply_hilbert_phase_shift(cufftComplex* input, cufftComplex* output, int size) { int idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < size) { // Apply phase shift for the Hilbert transform float phaseShift = (idx > size / 2) ? 1.0f : -1.0f; float tmp = input[idx].y; output[idx].y = input[idx].x*phaseShift; output[idx].x = -tmp*phaseShift; }}
__global__ void scale_data(float *data, cufftComplex* output, int n, float scale){ int idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < n) { output[idx].x = data[idx] *scale; output[idx].y = 0.0f; }}
__global__ void get_data(float *data, cufftComplex* output, int n){ int idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < n) { data[idx]= output[idx].x; }}
void hilbert_freq(float *indata, float *hilb, int n1, int n2){ cufftHandle plan; cufftComplex* inputComplex; cufftComplex* outputComplex; cufftResult result; cufftPlan1d(&plan, n1, CUFFT_C2C, 1); cudaMalloc((void**)&inputComplex, n1 * sizeof(cufftComplex)); cudaMalloc((void**)&outputComplex, n1 * sizeof(cufftComplex)); int threadsPerBlock = 256; int blocksPerGrid = (n1 + threadsPerBlock - 1) / threadsPerBlock; for(int i2=0; i2<n2; i2++){ cudaMemset(outputComplex, 0, n1 * sizeof(cufftComplex)); cudaMemset(inputComplex, 0, n1 * sizeof(cufftComplex)); scale_data<<<(n1+255)/256, 256>>>(&indata[i2*n1], inputComplex, n1, 1.0f /n1); result = cufftExecC2C(plan, inputComplex, inputComplex, CUFFT_FORWARD); if (result != CUFFT_SUCCESS) { fprintf(stderr, "CUFFT error: FFT execution failed, code %d \n", result); exit(1); } apply_hilbert_phase_shift<<<blocksPerGrid, threadsPerBlock>>>(inputComplex, outputComplex, n1); result = cufftExecC2C(plan, outputComplex, outputComplex, CUFFT_INVERSE); get_data<<<(n1+255)/256, 256>>>(&hilb[i2*n1], outputComplex, n1); if (result != CUFFT_SUCCESS) { fprintf(stderr, "CUFFT error: FFT execution failed, code %d \n", result); exit(1); } } cufftDestroy(plan); cudaFree(inputComplex); cudaFree(outputComplex);}
int main(int argc, char *argv[]){
int n1,n2; float *data, *hilb; float *d_data, *d_hilb; sf_file in, out;
sf_init (argc,argv);
in = sf_input("in"); out = sf_output("out");
if (SF_FLOAT != sf_gettype(in)) sf_error("Need float input"); if (!sf_histint(in,"n1",&n1)) sf_error("No n1= in input"); n2 = sf_leftsize(in,1);
data = sf_floatalloc(n1*n2); hilb = sf_floatalloc(n1*n2);
cudaMalloc((float**)&d_data,n1*n2*sizeof(float)); cudaMemset(d_data,0,n1*n2*sizeof(float)); cudaMalloc((float**)&d_hilb,n1*n2*sizeof(float)); cudaMemset(d_hilb,0,n1*n2*sizeof(float));
sf_floatread(data,n1*n2,in); cudaMemcpy(d_data,data,n1*n2*sizeof(float),cudaMemcpyHostToDevice);
hilbert_freq(d_data, d_hilb, n1, n2);
cudaMemcpy(hilb, d_hilb, n1*n2*sizeof(float), cudaMemcpyDeviceToHost);
sf_floatwrite(hilb,n1*n2,out);
cudaFree(d_data); cudaFree(d_hilb); exit(0);}