2

我正在尝试将 4800x9600 矩阵的行加在一起,得到一个 1x9600 的矩阵。

我所做的是将 4800x9600 拆分为 9,600 个长度为 4800 的矩阵。然后我对 4800 个元素进行缩减。

问题是,这真的很慢......

有人有什么建议吗?

基本上,我正在尝试实现 MATLAB 的 sum(...) 函数。

这是我验证过的代码可以正常工作,只是它真的很慢:

void reduceRows(Matrix Dresult,Matrix DA)
{
        //split DA into chunks
        Matrix Dchunk;
        Dchunk.h=1;Dchunk.w=DA.h;
        cudaMalloc((void**)&Dchunk.data,Dchunk.h*Dchunk.w*sizeof(float));

        Matrix DcolSum;
        DcolSum.h=1;DcolSum.w=1;
        //cudaMalloc((void**)&DcolSum.data,DcolSum.h*DcolSum.w*sizeof(float));

        int i;
        for(i=0;i<DA.w;i++)   //loop over each column
        {
                //printf("%d ",i);
                cudaMemcpy(Dchunk.data,&DA.data[i*DA.h],DA.h*sizeof(float),cudaMemcpyDeviceToDevice);
                DcolSum.data=&Dresult.data[i];
                reduceTotal(DcolSum,Dchunk);
        }
        cudaFree(Dchunk.data);
}

矩阵定义为:

typedef struct{
        long w;
        long h;
        float* data;
}Matrix;

ReduceTotal() 只是调用标准的 NVIDIA 缩减,对 Dchunk 中的所有元素求和,然后将答案放入 DcolSum 中。

如果找不到答案,我将在 CPU 上执行所有这些操作... ;(

提前谢谢了,

4

3 回答 3

3

不是在每一列上循环,而是在列上并行化。4600 个线程中的每一个都将其列中的 9600 个条目相加,并将总和放在结果向量中的适当位置。

如果您正在寻找一个库来简化 Cuda 的工作,我强烈推荐 Thrust:http ://code.google.com/p/thrust/

使用 Thrust,我将创建一个仿函数来将矩阵指针保存在设备内存中,然后将其映射到一系列列索引上。函子的 operator() 将获取一个索引,对矩阵的该列中的所有内容求和,然后返回总和。然后,您的总和将放在一个thrust::device_vector 中,而没有任何内存副本(甚至直接CUDA 调用)。

你的仿函数可能看起来像:

struct ColumnSumFunctor {
    const Matrix matrix;

    // Make a functor to sum the matrix
    ColumnSumFunctor(const Matrix& matrix);

    // Compute and return the sum of the specified column
    __device__
    int operator()(const int& column) const;
};
于 2010-07-27T03:28:05.413 回答
1

归约是GPGPU中非常基础的操作,应该很快,9600次归约也不应该很慢。

你用的是什么显卡?

我建议您将其拆分为 9600 个数组,每次将 4800 个元素的数组减少为一个结果。我建议你不要使用 reduceTotal,而是使用 CUDPP 来执行归约操作,CUDPP 就像 CUDA 的 STL。它的实施与性能有关。

http://code.google.com/p/cudpp/

于 2010-07-23T13:30:25.720 回答
0

我认为您的问题是您正在启动 9600X2 内核。这应该是一个简单的算法,可以表示为单个内核。

实现它的最天真的方法不会合并内存,但它很可能比你现在做的方式更快。

一旦你得到了天真的方法,然后合并你的内存读取:例如,让块中的每个线程将 16 个连续的浮点数读入共享内存,同步线程,然后将相关的 16 个浮点数累加到一个寄存器中,同步线程,然后重复

Computing SDK 有很多减少技术的例子。

于 2010-07-23T15:46:05.820 回答