Cuda 基于并行约简的核函数优化

Cuda 基于并行约简的核函数优化,cuda,parallel-processing,gpu,Cuda,Parallel Processing,Gpu,在我以前的一篇文章中,我问过如何改进内核函数。内核计算两个大小相等的矩阵的对应行之间的平方欧氏距离Eric给出了一个很好的建议,即每行使用一个螺纹块,然后应用并行缩减。在继续更详细的内容之前,我写这篇文章是因为我不想让上一篇文章变得更复杂,我要感谢Eric。下面我附上了.cu代码,该代码没有给出正确的结果 __global__ void cudaEuclid( float* A, float* B, float* C, int rows, int cols ) { extern __sh

在我以前的一篇文章中,我问过如何改进内核函数。内核计算两个大小相等的矩阵的对应行之间的平方欧氏距离Eric给出了一个很好的建议,即每行使用一个螺纹块,然后应用并行缩减。在继续更详细的内容之前,我写这篇文章是因为我不想让上一篇文章变得更复杂,我要感谢Eric。下面我附上了.cu代码,该代码没有给出正确的结果

__global__ void cudaEuclid( float* A, float* B, float* C, int rows, int cols )
{
    extern __shared__ float sdata[];

    unsigned int tid = threadIdx.x;
    unsigned int c = blockDim.x * blockIdx.x + threadIdx.x; // rows
    unsigned int r = blockDim.y * blockIdx.y + threadIdx.y; // cols


    sdata[ tid ] = ( A[ r*cols + c ] - B[ r*cols + c ] ) * ( A[ r*cols + c ] - B[ r*cols + c ] );

    __syncthreads();

    for ( unsigned int s = 1; s < blockDim.x; s*=2 ){
        if ( tid % (2*s) == 0 ){
            sdata[ tid ] += sdata[ tid + s ];
        }
    }
    __syncthreads();

    if ( tid == 0) C[blockIdx.x]=sdata[0];  
}

感谢您并为我的无知感到抱歉。

您使用的是动态分配的共享内存,但实际上并没有分配任何共享内存。内核启动应该有一个额外的参数,用于每个块共享内存的大小

cudaEuclid<<<dimGrid, dimBlock, threadsPerBlock*sizeof(float)>>>( d_A, d_B, d_C, rows, cols );
cudaEuclid(d_A,d_B,d_C,rows,cols);
  • 考虑使用减少-节省您从头开始重新实现的时间,并且经过调整
  • 如果你想自己编写代码,这里有一个比CUDA 1.1-beta版本更好的示例
您正在使用动态分配的共享内存,但实际上并没有分配任何共享内存。内核启动应该有一个额外的参数,用于每个块共享内存的大小

cudaEuclid<<<dimGrid, dimBlock, threadsPerBlock*sizeof(float)>>>( d_A, d_B, d_C, rows, cols );
cudaEuclid(d_A,d_B,d_C,rows,cols);
  • 考虑使用减少-节省您从头开始重新实现的时间,并且经过调整
  • 如果你想自己编写代码,这里有一个比CUDA 1.1-beta版本更好的示例
    sdata[tid]+=sdata[tid];=>您只需将相同的值添加两次 你需要做什么


    sdata[tid]+=sdata[tid+s]

    sdata[tid]+=sdata[tid];==>您只需将相同的值添加两次 你需要做什么


    sdata[tid]+=sdata[tid+s]

    感谢您的更正和链接。代码部分
    sdata[tid]=(A[r*cols+c]-B[r*cols+c])*(A[r*cols+c]-B[r*cols+c])您发现它正确吗?我有很多疑问。内核初始化是否正确?有什么建议吗?很抱歉出现这种问题,但我是一个非常初学者。我会使用CUB进行约简,因此将线程本地结果分配给一个变量,然后只调用CUB::reduce(计算差分一次,然后将其平方,编译器应该很好,但会使它更具可读性)。您的网格配置看起来很奇怪,宽度为1,高度为256,这将导致未恢复(性能差)的访问。我本来希望看到一块瓷砖,例如32x4。谢谢你对CUB的建议,但我更喜欢自己做。对于一个项目的范围来说,这不是一个最佳性能的游戏,但我在低水平的学术理解中寻找。再次感谢。如果你把它从简单到高级,那么reduce是一个很好的学习示例,但是对于任何真正的代码,我总是鼓励在可能的情况下重用库。您还应该看看扫描示例,很高兴看到一个明显的串行算法如何映射到并行架构。感谢您的更正和链接。代码部分
    sdata[tid]=(A[r*cols+c]-B[r*cols+c])*(A[r*cols+c]-B[r*cols+c])您发现它正确吗?我有很多疑问。内核初始化是否正确?有什么建议吗?很抱歉出现这种问题,但我是一个非常初学者。我会使用CUB进行约简,因此将线程本地结果分配给一个变量,然后只调用CUB::reduce(计算差分一次,然后将其平方,编译器应该很好,但会使它更具可读性)。您的网格配置看起来很奇怪,宽度为1,高度为256,这将导致未恢复(性能差)的访问。我本来希望看到一块瓷砖,例如32x4。谢谢你对CUB的建议,但我更喜欢自己做。对于一个项目的范围来说,这不是一个最佳性能的游戏,但我在低水平的学术理解中寻找。再次感谢。如果你把它从简单到高级,那么reduce是一个很好的学习示例,但是对于任何真正的代码,我总是鼓励在可能的情况下重用库。您还应该看看扫描示例,很高兴看到一个明显的串行算法如何映射到并行架构。