C magmablas_dgemm不适用于较大的网格大小

C magmablas_dgemm不适用于较大的网格大小,c,cuda,blas,magma,C,Cuda,Blas,Magma,我不熟悉使用cuda和magma库。我在试一些关于测试问题的函数,一个二维热方程。我编写的代码对于32、64和128的网格大小似乎非常有效。但对于256或更大的网格大小,它产生了错误的结果。我只是在这里发布了部分代码,刚好可以重现错误。传输最终矩阵并在matlab中查看它表明,第二次调用magmablasêdgemm将错误引入到解决方案中 有没有人知道为什么这个代码会在更大的网格尺寸下被破解 int main(int argc, char* argv[]) { // Get param

我不熟悉使用cuda和magma库。我在试一些关于测试问题的函数,一个二维热方程。我编写的代码对于32、64和128的网格大小似乎非常有效。但对于256或更大的网格大小,它产生了错误的结果。我只是在这里发布了部分代码,刚好可以重现错误。传输最终矩阵并在matlab中查看它表明,第二次调用magmablasêdgemm将错误引入到解决方案中

有没有人知道为什么这个代码会在更大的网格尺寸下被破解

int main(int argc, char* argv[]) 
{
    // Get parameters for problem set up
    int side_width = atoi(argv[1]); //assuming square grid, N/32 integer 
    double dx = 2.0 / (side_width-1);
    double dt = 0.25 * dx;
    //double Tend = dt*3;// 0.5; 


    // create memory pointers for derivative operator matrices and solution matrix
    double* U;
    double* Dleft;
    double* Dright;
    double* dev_U;
    double* dev_Dleft;
    double* dev_Dright;

    //initialize the MAGMA system
    magma_init();

    magma_int_t N = side_width;

    // temp variables required by MAGMA functions
    magma_int_t *piv, info, err;
    piv = (magma_int_t*)malloc(N*sizeof(magma_int_t));


    // Allocate memory for matrices on host and device
    err  = magma_dmalloc_cpu(&U, N*N);
    err += magma_dmalloc_cpu(&Dleft, N*N);
    err += magma_dmalloc_cpu(&Dright, N*N);
    err += magma_dmalloc(&dev_U, N*N);
    err += magma_dmalloc(&dev_Dleft, N*N);
    err += magma_dmalloc(&dev_Dright, N*N);  

    if (err){
        printf("error in allocation. err number = %d\n", err);
        exit(1);
    }


    // zero out matrices (not efficient but correct)
    for (int k=0; k<N*N; ++k ){
        U[k] = 1.0;
        Dleft[k] = 0.0;
        Dright[k] = 0.0;
    }


    //create derivative operator matrices
    double a = dt/2.0/dx/dx;
    double b = dt/dx/dx;
    Dleft[0] = 1.0;
    Dleft[N*N-1] = 1.0;
    for (int k=1; k<N-1; ++k) {
        Dleft[k*N + k-1] = -a;
        Dleft[k*N + k]   = 1+b;
        Dleft[k*N + k+1] = -a;

        Dright[k*N + k-1] = a;
        Dright[k*N + k]   = 1-b;
        Dright[k*N + k+1] = a;
    }

    // Determine block and thread amounts
    int grid_dim = ((side_width + 31)/32) ;
    int block_dim = 32;
    dim3 gridDim(grid_dim, grid_dim);
    dim3 blockDim(block_dim, block_dim);

    //copy data from host to device
    magma_dsetmatrix(N, N, U, N, dev_U, N); 
    magma_dsetmatrix(N, N, Dleft, N, dev_Dleft, N);
    magma_dsetmatrix(N, N, Dright, N, dev_Dright, N);

    // LU factorize the left hand operator matrix
    magma_dgetrf_gpu(N, N, dev_Dleft, N, piv, &info);


    double tn = 0; //time counter

    // needed to take first step outside while loop because of some tricky transpose nonsense happening
    tn += dt; 
    // compute explicit step :  Uhat=Dright*U^T
    magmablas_dgemm(MagmaTrans,MagmaNoTrans, N, N, N, 1.0f, dev_Dright, N, dev_U, N, 0.0f, dev_U, N);
    // implicit step solve :  Dleft*U=Uhat
    magma_dgetrs_gpu(MagmaTrans, N, N, dev_Dleft, N, piv, dev_U, N, &info);
    // compute explicit step :  Uhat=Dright*U^T
    magmablas_dgemm(MagmaTrans, MagmaTrans, N, N, N, 1.0f, dev_Dright, N, dev_U, N, 0.0f, dev_U, N);


    printf("GPU matrix U at time %3.3f \n ", tn);
    magma_dprint_gpu(16, 16, dev_U, N);  


    //copy solution from device to host
    magma_dgetmatrix(N, N, dev_U, N, U, N);


    //write data to file
    char filename[256];
    char str_t[128];
    sprintf(str_t, "%d", N );
    sprintf(filename, "ADI_%s.bin", str_t);
    FILE* fileID = fopen(filename, "wb");
    for (int i=0; i<N*N; ++i){
        fwrite(&U[i],sizeof(double),1,fileID);
    }       
    fclose(fileID);

    free(U);
    free(Dleft);
    free(Dright);
    magma_free(dev_U);
    magma_free(dev_Dleft);
    magma_free(dev_Dright);
    free(piv);


    magma_finalize();

    return 0;

}
intmain(intargc,char*argv[])
{
//获取问题设置的参数
int side_width=atoi(argv[1]);//假设为正方形网格,N/32整数
双dx=2.0/(侧边宽度-1);
双dt=0.25*dx;
//双趋势=dt*3;//0.5;
//为导数运算符矩阵和解矩阵创建内存指针
双*U;
双*Dleft;
双*驱动;
双*dev_;
双*dev_Dleft;
双*dev_Dright;
//初始化岩浆系统
magma_init();
岩浆内部=侧面宽度;
//MAGMA函数所需的临时变量
magma_int_t*piv、信息、错误;
piv=(岩浆内部)malloc(N*sizeof(岩浆内部));
//为主机和设备上的矩阵分配内存
err=magma\U dmalloc\U cpu(&U,N*N);
err+=magma\u dmalloc\u cpu(&Dleft,N*N);
err+=magma\u dmalloc\u cpu(&Dright,N*N);
err+=magma\U dmalloc(&dev\U,N*N);
err+=岩浆(和发展,N*N);
err+=岩浆(和发展动力,N*N);
如果(错误){
printf(“分配错误。错误号=%d\n”,错误);
出口(1);
}
//归零矩阵(效率不高但正确)

就我所知,对于(int k=0;k),BLAS/LAPACK gemm从未支持就地操作,即

C := alpha*op( A )*op( B ) + beta*C
不能转化为

A := alpha*op( A )*op( B ) + beta*A

在保证正确性的情况下,即使是对于α=1,β=0的规范情况也是如此。如果您可以使用fortran,我建议您查看来自Dongarra组的。如果矩阵指针以a或B的形式传递,则该实现将中断

在多线程或大规模并行BLAS实现中,这一点尤其正确。大多数并行执行环境不支持任何类型的强或固定执行顺序。这可能意味着无意中在线性代数例程的串行版本中工作的操作会并行中断,因为缺少执行顺序如果并行BLAS或LAPACK实现中的一个例程没有明确表示它支持就地操作,请不要假设它支持就地操作,因为所有这些都有龙


你的MAGMA gemm调用只是偶然地在较小的大小下工作,可能是因为非常小的矩阵大小没有暴露足够的并行性来解决由于输入和输出指针别名而产生的正确性问题。如果你更改代码,使输入和输出是不同的内存分配,我怀疑问题会被解决出现。

当你谈论“网格大小”时,你的意思是什么?它是
侧边宽度的值吗?你确定
magma\u dgemm
支持就地点积吗?如果它们是…我会感到惊讶。是的,网格大小是侧边宽度。2D域被离散成一个NxN点数组(N=侧边宽度)。使用magmablas_dgemm是为了矩阵乘法,而不是点积。你是说magma不会进行就地矩阵乘法吗?我想它会跟随Lapack,并允许从A*C分配值给C?为什么它在128或更少的网格下工作得很好?是的,这就是问题所在。谢谢你的详细解释说明。我的代码使用临时矩阵,而不是就地编写,现在它可以完美地工作。:)
B := alpha*op( A )*op( B ) + beta*B