我有一个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~300
,dimx~3000
,dimy~20
解决此问题的最佳(最快)方式是什么?
答案 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
循环的情况,您可以考虑两种可能的改进:
>=3.5
的卡,您可以通过将for
循环与CUDA内核交换并从内部启动提到的cuBLAS例程,为这种方法提供更高程度的并行性内核。