我有一個M*N
主機內存矩陣,並在複製到設備內存時,我需要它被轉置爲N*M
矩陣。有沒有任何cuda(cuBLAS ...)API這樣做?我正在使用CUDA 4.謝謝!在CUDA中轉換矩陣的最有效方法是什麼?
回答
cublas<t>geam()
This function performs the matrix-matrix addition/transposition
the user can transpose matrix A by setting *alpha=1 and *beta=0.
(並指定transa操作者如對CUBLAS_OP_T轉置)
謝謝羅伯特!但是我意識到cubas
在很多情況下,不需要顯式轉換,因爲您可以簡單地使用大多數BLAS函數提供的轉置標誌。以下白皮書描述瞭如果必須將其作爲單獨的步驟完成轉換,請執行以下白皮書:http://docs.nvidia.com/cuda/samples/6_Advanced/transpose/doc/MatrixTranspose.pdf – njuffa 2013-03-17 20:25:09
另請參閱以前的問題: http://stackoverflow.com/questions/13782012/how-to-transpose-a-matrix-in-cuda-cublas?rq=1 – njuffa 2013-03-17 20:29:04
CULA具有輔助例程來計算轉置(culaDevice?geTranspose
)。在矩形矩陣的情況下,您也可以使用就地換位(culaDevise?geTransposeInplace
)。
注意:如果您符合特定條件,CULA有免費許可證。
爲了回答您關於效率的問題,我比較了兩種方法來執行矩陣轉置,一種使用Thrust庫,另一種使用Robert Crovella建議的使用cublas<t>geam
。比較的結果是一個開普勒K20C卡在以下方面:
| Matrix size | Thrust [ms] | cuBLAS [ms] |
| | | |
| 32x32 | 0.015 | 0.016 |
| 64x64 | 0.015 | 0.017 |
| 128x128 | 0.019 | 0.017 |
| 256x256 | 0.028 | 0.017 |
| 512x512 | 0.088 | 0.042 |
| 1024x1024 | 0.34 | 0.13 |
| 2048x2048 | 1.24 | 0.48 |
| 4096x4096 | 11.02 | 1.98 |
如可以看到的,使用cublas<t>geam
推力勝過版本。以下是執行比較的代碼。
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/functional.h>
#include <thrust/gather.h>
#include <thrust/scan.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <iostream>
#include <iomanip>
#include <cublas_v2.h>
#include <conio.h>
#include <assert.h>
/**********************/
/* cuBLAS ERROR CHECK */
/**********************/
#ifndef cublasSafeCall
#define cublasSafeCall(err) __cublasSafeCall(err, __FILE__, __LINE__)
#endif
inline void __cublasSafeCall(cublasStatus_t err, const char *file, const int line)
{
if(CUBLAS_STATUS_SUCCESS != err) {
fprintf(stderr, "CUBLAS error in file '%s', line %d\n \nerror %d \nterminating!\n",__FILE__, __LINE__,err);
getch(); cudaDeviceReset(); assert(0);
}
}
// convert a linear index to a linear index in the transpose
struct transpose_index : public thrust::unary_function<size_t,size_t>
{
size_t m, n;
__host__ __device__
transpose_index(size_t _m, size_t _n) : m(_m), n(_n) {}
__host__ __device__
size_t operator()(size_t linear_index)
{
size_t i = linear_index/n;
size_t j = linear_index % n;
return m * j + i;
}
};
// convert a linear index to a row index
struct row_index : public thrust::unary_function<size_t,size_t>
{
size_t n;
__host__ __device__
row_index(size_t _n) : n(_n) {}
__host__ __device__
size_t operator()(size_t i)
{
return i/n;
}
};
// transpose an M-by-N array
template <typename T>
void transpose(size_t m, size_t n, thrust::device_vector<T>& src, thrust::device_vector<T>& dst)
{
thrust::counting_iterator<size_t> indices(0);
thrust::gather
(thrust::make_transform_iterator(indices, transpose_index(n, m)),
thrust::make_transform_iterator(indices, transpose_index(n, m)) + dst.size(),
src.begin(),dst.begin());
}
// print an M-by-N array
template <typename T>
void print(size_t m, size_t n, thrust::device_vector<T>& d_data)
{
thrust::host_vector<T> h_data = d_data;
for(size_t i = 0; i < m; i++)
{
for(size_t j = 0; j < n; j++)
std::cout << std::setw(8) << h_data[i * n + j] << " ";
std::cout << "\n";
}
}
int main(void)
{
size_t m = 5; // number of rows
size_t n = 4; // number of columns
// 2d array stored in row-major order [(0,0), (0,1), (0,2) ... ]
thrust::device_vector<double> data(m * n, 1.);
data[1] = 2.;
data[3] = 3.;
std::cout << "Initial array" << std::endl;
print(m, n, data);
std::cout << "Transpose array - Thrust" << std::endl;
thrust::device_vector<double> transposed_thrust(m * n);
transpose(m, n, data, transposed_thrust);
print(n, m, transposed_thrust);
std::cout << "Transpose array - cuBLAS" << std::endl;
thrust::device_vector<double> transposed_cuBLAS(m * n);
double* dv_ptr_in = thrust::raw_pointer_cast(data.data());
double* dv_ptr_out = thrust::raw_pointer_cast(transposed_cuBLAS.data());
double alpha = 1.;
double beta = 0.;
cublasHandle_t handle;
cublasSafeCall(cublasCreate(&handle));
cublasSafeCall(cublasDgeam(handle, CUBLAS_OP_T, CUBLAS_OP_T, m, n, &alpha, dv_ptr_in, n, &beta, dv_ptr_in, n, dv_ptr_out, m));
print(n, m, transposed_cuBLAS);
getch();
return 0;
}
+1非常具有啓發性。 – 2014-02-16 03:17:36
你可以嘗試解釋巨大差異的起源嗎?他們是由一個顯着不同的算法造成的?可以在推力版本中優化內存訪問嗎? – 2015-07-01 09:14:26
- 1. 在文本文件中轉換矩陣的有效方法是什麼?
- 2. 做矩陣運算matlab的最有效方法是什麼?
- 3. 什麼是將SymPy矩陣轉換爲numpy數組/矩陣的最佳方法
- 4. 在c#中存儲二進制矩陣的最有效的方法是什麼?
- 5. 什麼是將DataTable轉換爲對象的最有效方法[,]?
- 6. 在Matlab中用矩陣替換矩陣的所有非空元素的最佳方法是什麼?
- 7. 什麼是在Javascript中反轉數組的最有效方法?
- 8. 將CSV轉換爲R中稀疏矩陣的有效方法
- 9. 什麼是在MATLAB中展開矩陣的最快方法?
- 10. 矩陣乘法矩陣及其在CUDA中的轉置
- 11. 在Android中將圖像轉換爲Base64的最有效方法是什麼?
- 12. 將matlab矩陣轉換爲C++數組的有效方法
- 13. CUDA中的非方形矩陣乘法
- 14. 用極稀疏矩陣乘法的最快方法是什麼?
- 15. 矩陣乘法的最快方法是什麼?
- 16. 轉換矩陣的方陣
- 17. 在C++中實現大輸入矩陣的最有效方法?
- 18. 在python中初始化矩陣的最有效方法
- 19. 用-1替換矩陣中的空元素的最佳方法是什麼? MATLAB
- 20. 什麼是將矩陣矩陣轉換爲三角形條的快速算法?
- 21. Eigen中有效的矩陣轉置矩陣乘法
- 22. 什麼是C++中最高效的矩陣表示?
- 23. 在MATLAB中迭代矩陣列的最佳方式是什麼?
- 24. 扭轉BitArray順序的最有效方法是什麼?
- 25. numpy矩陣加法的有效方法
- 26. 什麼是密集矩陣向量乘法的最有效的實現?
- 27. Cuda矩陣加法
- 28. 矩陣乘法CUDA
- 29. Cuda矩陣乘法
- 30. 按值排序二維矩陣的最佳方法是什麼?
它是[文件]中的右(http://docs.nvidia.com/cuda/cublas/index.html#topic_9_1),如果你注意看.... – talonmies 2013-03-17 08:05:37
謝謝!但是,由於觀察到cublas迴歸,並且很長一段時間後提交nVidia錯誤報告後沒有迴應,我正在使用CUDA4而不是CUDA5。 – 2013-03-17 18:26:03