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);
}
Hilbert 变换
https://tuoyuangui.github.io/website/posts/typora/数学方法/hilbert变换/
作者
椭圆规/tuoyuangui
发布于
2024-01-13
许可协议
CC BY-NC-SA 4.0