在CUDA中查找矩阵的每列的最大值

时间:2014-05-21 07:11:36

标签: cuda

我有一个3D矩阵(dimx x dimy x N)在CUDA设备中展平成一维数组。

我想为每个2D矩阵(dimx x dimy切片)的每一列找到一个最大值数组,从而得到dimy x N最大值的二维矩阵。

例如(行主要订单)

N = 2, dimx = 2, dimy = 3 

A = {1, 5, 2, 
     4, 2, 4,

     4, 3, 2,
     1, 5, 3}; 

我想知道,

{4, 5, 4,  
 4, 5, 3}

作为最大值的矩阵,在这种情况下。

使用GPU通过N~300dimx~3000dimy~20解决此问题的最佳(最快)方式是什么?

1 个答案:

答案 0 :(得分:1)

解决问题的一种简单方法是使用cublasI<t>amax()

如果您拥有每个MxN二维矩阵的列主要存储空间,则可以cublasI<t>amax()多次使用incx=1,每列一次每个2D矩阵。

如果您有行主存储空间,则可以通过将incx设置为等于列数N来解决问题。

下面您将找到一个简单的示例,说明如何针对列主要和行主要排序的情况为单个MxN 2D矩阵执行此操作。如果您认为3D矩阵可以存储为后续2D矩阵,那么3D情况的扩展就会变得更加困难。换句话说,对于下面的示例,您应该只更改索引和所涉及的偏移量。

#include <thrust\device_vector.h>

#include <cublas_v2.h>

// Matrix A
// [1 5 3]
// [6 2 4]

void main(){

    const int M = 2;
    const int N = 3;

    thrust::host_vector<float> h_data(M*N);
    thrust::device_vector<float> d_data(M*N);

    // --- Column major ordering
    h_data[0] = 1.f; h_data[1] = 6.f;
    h_data[2] = 5.f; h_data[3] = 2.f;
    h_data[4] = 3.f; h_data[5] = 4.f;

    d_data = h_data;

    cublasHandle_t handle;
    cublasCreate(&handle);

    int result;

    for (int i=0; i<N; i++) {

        cublasIsamax(handle, M, (float*)thrust::raw_pointer_cast(d_data.data())  + i*M, 1, &result);
        printf("%i %f\n",result,h_data[i*M+result-1]);

    }

    // --- Row major ordering
    h_data[0] = 1.f; h_data[1] = 5.f; h_data[2] = 3.f;
    h_data[3] = 6.f; h_data[4] = 2.f; h_data[5] = 4.f;

    d_data = h_data;

    for (int i=0; i<N; i++) {

        cublasIsamax(handle, M, (float*)thrust::raw_pointer_cast(d_data.data())  + i, N, &result);
        printf("%i %f\n",result,h_data[i+(result-1)*N]);

    }

    getchar();

}

修改

应该注意上面代码中的M对应于您的dimx(列大小),而上面代码中的N对应于您的dimy(行尺寸)。在您的问题中,您假设dimx>>dimy,因此循环20周期不应该是一个大问题。当然,我在下面概述的方法需要在2D矩阵的数量上进一步for循环(你定义为N)。请注意,您始终可以在一个循环中合并两个for循环。为了改善for循环的情况,您可以考虑两种可能的改进:

  1. 使用CUDA流尝试尽可能多地填充GPU;
  2. 如果您有一张具有计算能力>=3.5的卡,您可以通过将for循环与CUDA内核交换并从内部启动提到的cuBLAS例程,为这种方法提供更高程度的并行性内核。