我正在使用“标准”CUDA实现和复数(浮动2)上的“基于纹理”的CUDA实现来比较一维线性插值。
“标准”CUDA实施包括以下几行:
/*************************************/
/* LINEAR INTERPOLATION KERNEL - GPU */
/*************************************/
__device__ float linear_kernel_GPU(float in)
{
float d_y;
return 1.-abs(in);
}
/**********************************************/
/* LINEAR INTERPOLATION KERNEL FUNCTION - GPU */
/**********************************************/
__global__ void linear_interpolation_kernel_function_GPU(float2* result_d, float2* data_d, float* x_in_d, float* x_out_d, int M, int N)
{
int j = threadIdx.x + blockDim.x * blockIdx.x;
if(j<N)
{
result_d[j].x = 0.;
result_d[j].y = 0.;
for(int k=0; k<M; k++)
{
if (fabs(x_out_d[j]-x_in_d[k])<1.) {
result_d[j].x = result_d[j].x + linear_kernel_GPU(x_out_d[j]-x_in_d[k])*data_d[k].x;
result_d[j].y = result_d[j].y + linear_kernel_GPU(x_out_d[j]-x_in_d[k])*data_d[k].y; }
}
}
}
extern "C" void linear_interpolation_function_GPU(cuComplex* result_d, cuComplex* data_d, float* x_in_d, float* x_out_d, int M, int N){
dim3 dimBlock(BLOCK_SIZE,1); dim3 dimGrid(N/BLOCK_SIZE + (N%BLOCK_SIZE == 0 ? 0:1),1);
linear_interpolation_kernel_function_GPU<<<dimGrid,dimBlock>>>(result_d, data_d, x_in_d, x_out_d, M, N);
}
“基于纹理”的CUDA实现包括以下几行:
texture<float2, 1, cudaReadModeElementType> data_d_texture;
// ********************************************************/
// * LINEAR INTERPOLATION KERNEL FUNCTION - GPU - TEXTURE */
// ********************************************************/
__global__ void linear_interpolation_kernel_function_GPU_texture(cuComplex* result_d, float* x_out_d, int M, int N)
{
int j = threadIdx.x + blockDim.x * blockIdx.x;
if(j<N) result_d[j] = tex1D(data_d_texture,float(x_out_d[j]+M/2+0.5));
}
// *************************************************/
// * LINEAR INTERPOLATION FUNCTION - GPU - TEXTURE */
// *************************************************/
extern "C" void linear_interpolation_function_GPU_texture(float2* result_d, float2* data, float* x_in_d, float* x_out_d, int M, int N){
cudaArray* data_d = NULL; cudaMallocArray (&data_d, &data_d_texture.channelDesc, M, 1);
cudaMemcpyToArray(data_d, 0, 0, data, sizeof(float2)*M, cudaMemcpyHostToDevice);
cudaBindTextureToArray(data_d_texture, data_d);
data_d_texture.normalized = false;
data_d_texture.filterMode = cudaFilterModeLinear;
dim3 dimBlock(BLOCK_SIZE,1); dim3 dimGrid(N/BLOCK_SIZE + (N%BLOCK_SIZE == 0 ? 0:1),1);
linear_interpolation_kernel_function_GPU_texture<<<dimGrid,dimBlock>>>(result_d, x_out_d, M, N);
}
“基于纹理”的插值比“标准”插值快20多倍。但是,我注意到结果中存在一些不匹配,两个约为0.07%
的实现之间存在均方根误差。
CUDA C编程指南说,插值系数以9位定点格式存储,具有8位小数值,这可能是造成这种不匹配的原因。
我有两个问题:
1)是否有任何“技巧”来提高“基于纹理”插值的准确性?
2)我认为即使我移动到float4,这个9位表示也会将精度限制在此处,对吧?换句话说,将数字表示精度从float2增加到float4没有意义吗?
提前致谢。
答案 0 :(得分:2)
您可以“预先插入”纹理以提高分辨率,即如果您的初始纹理是100x100,那么您可以预先插值使其达到200x200,然后您将内核插值的分辨率加倍。 / p>