我正在尝试在CUDA中实现一个FIR(有限脉冲响应)滤波器。我的方法非常简单,看起来有点像这样:
过滤器是有效的,但由于我刚开始学习CUDA编程,不确定如何进行优化。
我发现一个小问题是,在我打算使用过滤器的应用程序中,无法预先知道"dataLength"、"filteredDataLength"和"numeratorLength"的值。而且,尽管在上面的代码中,"dataLength"是32的倍数,在最终的应用程序中也不能保证是这样的。
当我将我的代码与ArrayFire进行比较时,我的代码执行时间大约需要三倍。
是否有人有任何想法如何加速处理?
编辑:已将所有“filterLength”更改为“numeratorLength”。
#include <cuda.h>
__global__ void filterData(const float *d_data,
const float *d_numerator,
float *d_filteredData,
const int numeratorLength,
const int filteredDataLength)
{
int i = blockDim.x * blockIdx.x + threadIdx.x;
float sum = 0.0f;
if (i < filteredDataLength)
{
for (int j = 0; j < numeratorLength; j++)
{
// The first (numeratorLength-1) elements contain the filter state
sum += d_numerator[j] * d_data[i + numeratorLength - j - 1];
}
}
d_filteredData[i] = sum;
}
int main(void)
{
// (Skipping error checks to make code more readable)
int dataLength = 18042;
int filteredDataLength = 16384;
int numeratorLength= 1659;
// Pointers to data, filtered data and filter coefficients
// (Skipping how these are read into the arrays)
float *h_data = new float[dataLength];
float *h_filteredData = new float[filteredDataLength];
float *h_filter = new float[numeratorLength];
// Create device pointers
float *d_data = nullptr;
cudaMalloc((void **)&d_data, dataLength * sizeof(float));
float *d_numerator = nullptr;
cudaMalloc((void **)&d_numerator, numeratorLength * sizeof(float));
float *d_filteredData = nullptr;
cudaMalloc((void **)&d_filteredData, filteredDataLength * sizeof(float));
// Copy data to device
cudaMemcpy(d_data, h_data, dataLength * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_numerator, h_numerator, numeratorLength * sizeof(float), cudaMemcpyHostToDevice);
// Launch the kernel
int threadsPerBlock = 256;
int blocksPerGrid = (filteredDataLength + threadsPerBlock - 1) / threadsPerBlock;
filterData<<<blocksPerGrid,threadsPerBlock>>>(d_data, d_numerator, d_filteredData, numeratorLength, filteredDataLength);
// Copy results to host
cudaMemcpy(h_filteredData, d_filteredData, filteredDataLength * sizeof(float), cudaMemcpyDeviceToHost);
// Clean up
cudaFree(d_data);
cudaFree(d_numerator);
cudaFree(d_filteredData);
// Do stuff with h_filteredData...
// Clean up some more
delete [] h_data;
delete [] h_filteredData;
delete [] h_filter;
}
过滤器是有效的,但由于我刚开始学习CUDA编程,不确定如何进行优化。
我发现一个小问题是,在我打算使用过滤器的应用程序中,无法预先知道"dataLength"、"filteredDataLength"和"numeratorLength"的值。而且,尽管在上面的代码中,"dataLength"是32的倍数,在最终的应用程序中也不能保证是这样的。
当我将我的代码与ArrayFire进行比较时,我的代码执行时间大约需要三倍。
是否有人有任何想法如何加速处理?
编辑:已将所有“filterLength”更改为“numeratorLength”。