是否有cuda函数从主列中的矩阵复制行?

是否有cuda函数从主列中的矩阵复制行?,cuda,cublas,Cuda,Cublas,我有一个设备矩阵U的尺寸MxN在列主要排序。现在我想把行K提取成向量u。是否有一个功能来实现这一点?注:副本需要考虑K的偏移和M的跨步 我一直在看函数,但它没有敲响警钟,来自一个更拉帕克风格的API。我不明白这些音高参数是什么,为什么它们不被简单地称为行和列或M和N?第一部分的答案是否定的。GPU内部的内存是线性的,就像主机端一样。如果只希望访问按列主顺序保存的二维矩阵的行元素,则由于非合并访问,成本会很高。由于GPU内存是按段配置的,因此对元素的每次访问不仅需要获取元素本身,还需要获取段中的相

我有一个设备矩阵U的尺寸MxN在列主要排序。现在我想把行K提取成向量u。是否有一个功能来实现这一点?注:副本需要考虑K的偏移和M的跨步


我一直在看函数,但它没有敲响警钟,来自一个更拉帕克风格的API。我不明白这些音高参数是什么,为什么它们不被简单地称为行和列或M和N?

第一部分的答案是否定的。GPU内部的内存是线性的,就像主机端一样。如果只希望访问按列主顺序保存的二维矩阵的行元素,则由于非合并访问,成本会很高。由于GPU内存是按段配置的,因此对元素的每次访问不仅需要获取元素本身,还需要获取段中的相邻元素,在列主顺序中,这些元素恰好是元素所在列的大部分元素。如果按行主顺序存储矩阵并访问行中的元素,GPU会尝试将同时的内存请求合并到最小的段事务中。

,这是保存2D数据的首选方法,它填充内存分配,以便长度<代码>宽度的每一行/列的起始地址驻留在段的起始地址中。因此,当您访问行/列的所有元素时,获取的段将最小化。使用这种方法的成本是浪费内存空间。

第一部分的答案是否定的。GPU内部的内存是线性的,就像主机端一样。如果只希望访问按列主顺序保存的二维矩阵的行元素,则由于非合并访问,成本会很高。由于GPU内存是按段配置的,因此对元素的每次访问不仅需要获取元素本身,还需要获取段中的相邻元素,在列主顺序中,这些元素恰好是元素所在列的大部分元素。如果按行主顺序存储矩阵并访问行中的元素,GPU会尝试将同时的内存请求合并到最小的段事务中。

,这是保存2D数据的首选方法,它填充内存分配,以便长度<代码>宽度的每一行/列的起始地址驻留在段的起始地址中。因此,当您访问行/列的所有元素时,获取的段将最小化。使用此方法的成本是浪费内存空间。

正如@Farzad所指出的,您想要的操作的内存访问模式效率低下,但除此之外,您想要的可以通过调用cudaMemcpy2D来实现(假设u和u的类型为int):


正如@Farzad所指出的,您想要的操作的内存访问模式效率低下,但除此之外,您想要的可以通过调用cudaMemcpy2D来实现(假设u和u的类型为int):

你可以用

cublas<t>copy(handle, N, U+K, M, u, 1);
cublascopy(手柄,N,U+K,M,U,1);
作为

#包括
#包括
#包括
#包括
/***********************/
/*CUDA错误检查*/
/***********************/
#定义gpuerchk(ans){gpuAssert((ans),_文件_,_行__)}
内联void gpuAssert(cudaError\u t代码,char*文件,int行,bool abort=true)
{
如果(代码!=cudaSuccess)
{
fprintf(标准,“GPUassert:%s%s%d\n”,cudaGetErrorString(代码)、文件、行);
如果(中止)退出(代码);
}
}
/*************************/
/*库布拉斯错误检查*/
/*************************/
#ifndef cublasSafeCall
#定义cublasSafeCall(err)uu cublasSafeCall(err,u u文件,_u行_;)
#恩迪夫
内联void\uuu cublasSafeCall(cublasStatus\u t err、const char*文件、const int line)
{
if(CUBLAS\u STATUS\u SUCCESS!=错误){
fprintf(stderr,“文件“%s”中的CUBLAS错误,第%d行\n\n错误%d\n终止!\n“,\uuuuu文件,\uuuu行\uuuu,错误);
getch();cudaDeviceReset();断言(0);
}
}
int main(){
常数int M=5;
常数int N=4;
常数int K=2;
立方手柄;
cublasafecall(cublasCreate(&handle));
float*U=(float*)malloc(M*N*sizeof(float));
浮动*d_;
gpuErrchk(cudaMalloc(void**)和d_,M*N*sizeof(float));
float*u=(float*)malloc(M*sizeof(float));
浮动*d_;
gpuErrchk(cudaMalloc((void**)和d_,N*sizeof(float));
对于(int j=0;j您可以使用

cublas<t>copy(handle, N, U+K, M, u, 1);
cublascopy(手柄,N,U+K,M,U,1);
作为

#包括
#包括
#包括
#包括
/***********************/
/*CUDA错误检查*/
/***********************/
#定义gpuerchk(ans){gpuAssert((ans),_文件_,_行__)}
内联void gpuAssert(cudaError\u t代码,char*文件,int行,bool abort=true)
{
如果(代码!=cudaSuccess)
{
fprintf(标准,“GPUassert:%s%s%d\n”,cudaGetErrorString(代码)、文件、行);
如果(中止)退出(代码);
}
}
/*************************/
/*库布拉斯错误检查*/
/*************************/
#ifndef cublasSafeCall
#定义cublasSafeCall(err)uu cublasSafeCall(err,u u文件,_u行_;)
#恩迪夫
内联void\uuu cublasSafeCall(cublasStatus\u t err、const char*文件、const int line)
{
if(CUBLAS\u STATUS\u SUCCESS!=错误){
fprintf(stderr,“文件“%s”中的CUBLAS错误,第%d行\n\n错误%d\n终止!\n“,\uuuuu文件,\uuuu行\uuuu,错误);
getch();cudaDeviceReset();断言(0);
}
}
int main(){
常数int M=5;
常数int N=4;
常数int K=2;
立方手柄;
cublasafecall(cublasCreate(&handle));
float*U=(float*)malloc(M*N*sizeof(float));
浮动*d_;
gpuErrchk(cudaMalloc(void**)和d_,M*N*sizeof(float));
float*u=(float*)malloc(M*sizeof(float));
浮动*d_;
gpuErrchk(cudaMalloc((void**)和d_,N*sizeof(float));
对于(int j=0;j如何使用
cublascopy()
并正确使用
incx
incy
,与行长相关?宽度和节距(填充宽度)如中所示
#include<stdio.h>
#include<conio.h>
#include<assert.h>

#include<cublas_v2.h>

/***********************/
/* CUDA ERROR CHECKING */
/***********************/
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
    if (code != cudaSuccess) 
    {
        fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);     
        if (abort) exit(code);
    }
}

/*************************/
/* cuBLAS ERROR CHECKING */
/*************************/
#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); 
    }
}

int main() {

    const int M = 5;
    const int N = 4;
    const int K = 2;

    cublasHandle_t handle;
    cublasSafeCall(cublasCreate(&handle));

    float* U = (float*)malloc(M*N*sizeof(float));
    float* d_U; 
    gpuErrchk(cudaMalloc((void**)&d_U,M*N*sizeof(float)));

    float* u = (float*)malloc(M*sizeof(float));
    float* d_u;
    gpuErrchk(cudaMalloc((void**)&d_u,N*sizeof(float)));

    for (int j=0; j<N; j++) 
        for (int i=0; i<M; i++) 
            U[j*M+i] = (float)(i*j); // Column-major ordering

    printf("K-th row - Input\n");
    for (int j=0; j<N; j++) printf("U(K,%i) =  %f\n",j,U[j*M+K]);
    printf("\n\n");

    gpuErrchk(cudaMemcpy(d_U,U,M*N*sizeof(float),cudaMemcpyHostToDevice));

    cublasSafeCall(cublasScopy(handle, N, d_U+K, M, d_u, 1));

    gpuErrchk(cudaMemcpy(u,d_u,N*sizeof(float),cudaMemcpyDeviceToHost));

    printf("K-th row - Output\n");
    for (int j=0; j<N; j++) printf("u(%i) =  %f\n",j,u[j]);

    getchar();

}