CUDA二维阵列nvidia

CUDA二维阵列nvidia,cuda,nvidia,cuda-gdb,Cuda,Nvidia,Cuda Gdb,我正在对2D阵列使用cudamallocitch和cudaMemcpy2D。我不确定我的编码是否正确,即使我不能正确地获得输出。有人能帮忙吗?有人能调试我的错误吗?提前谢谢 #include<stdio.h> #include<cuda.h> #define siz 4*sizeof(int) __global__ void addmatrix(int *m1,int *m2,size_t pitch) { int r=threadIdx.x; int *

我正在对2D阵列使用
cudamallocitch
cudaMemcpy2D
。我不确定我的编码是否正确,即使我不能正确地获得输出。有人能帮忙吗?有人能调试我的错误吗?提前谢谢

#include<stdio.h>
#include<cuda.h>
#define siz 4*sizeof(int)
__global__ void addmatrix(int *m1,int *m2,size_t pitch)
{
    int r=threadIdx.x;
    int *r1=m1+r*pitch;
    int *r2=m2+r*pitch;
    int c;
    for(c=1;c<=4;c++)
    {
        r1[c]+=r2[c];
    }
}
int main()
{
    int i,j;
    int **m1_c,**m2_c;
    int *m1_d,*m2_d;
    size_t pitch;
    cudaError_t err;
    m1_c=(int **)malloc(4*sizeof(int *));
    for(i=1;i<=4;i++)
    {
        m1_c[i]=(int *)malloc(siz);
    }
    m2_c=(int **)malloc(4*sizeof(int *));
    for(i=1;i<=4;i++)
    {
        m2_c[i]=(int *)malloc(siz);
    }
    for(i=1;i<=4;i++)
    {
        for(j=1;j<=4;j++)
        {
            m1_c[i][j]=rand()%10;
            m2_c[i][j]=rand()%10;
        }
    }
    for(i=1;i<=4;i++)
    {
        for(j=1;j<=4;j++)
        {
            printf("%d\t",m1_c[i][j]);
        }
        printf("\n");
    }
    printf("\n\n");
    for(i=1;i<=4;i++)
    {
        for(j=1;j<=4;j++)
        {
            printf("%d\t",m2_c[i][j]);
        }
        printf("\n");
    }
    err=cudaMallocPitch((void **)&m1_d,&pitch,siz,siz);
    err=cudaMallocPitch((void **)&m2_d,&pitch,siz,siz);
    err=cudaMemcpy2D(m1_d,pitch,m1_c,siz,siz,4,cudaMemcpyHostToDevice);
    err=cudaMemcpy2D(m2_d,pitch,m2_c,siz,siz,4,cudaMemcpyHostToDevice);
    dim3 grid(1);
    dim3 block(16);
    addmatrix<<<grid,block>>>(m1_d,m2_d,siz);
    cudaMemcpy2D(m1_c,siz,m1_d,pitch,siz,4,cudaMemcpyDeviceToHost);

    for(i=1;i<=4;i++)
    {
        for(j=1;j<=4;j++)
        {
            printf("%d\t",m1_c[i][j]);
        }
        printf("\n");
    }
    err=cudaFree(m1_d);
    err=cudaFree(m2_d);
    err=cudaDeviceReset();      
}
#包括
#包括
#定义大小4*sizeof(int)
__全局无效添加矩阵(int*m1,int*m2,大小\u t间距)
{
int r=threadIdx.x;
int*r1=m1+r*节距;
int*r2=m2+r*节距;
INTC;

对于(c=1;c),此代码存在几个问题。没有特定顺序:

  • 您正在通过从1到4的各种数组进行索引,但这在C中是不正确的。C索引从零开始,并小于维度1。这与CUDA无关
  • 需要两个指针(
    src
    dst
    ),这两个指针都是指向内存中线性数组的指针。我意识到这很混乱,因为描述中到处都是2D,但这两个指针参数基本上都是同一类型的(指向内存的指针),并且您正在传递两种不同类型的指针(一个是指向内存的指针,另一个是指向内存指针的指针)。因此,从cudaMemcpy2D的定义来看,您的使用不可能是正确的。关于如何使用cudaMemcpy2D,有很多已回答的问题和示例,我建议您搜索并查看其中的一些问题。请注意,解决此问题可能会导致您从根本上重新考虑如何在主机矩阵上存储数据。有有很多问题,例如关于处理多维矩阵的问题——如果可能的话,您应该将它们展平。请注意,在您当前的代码中,使用cudaMemcpy2D时出现的此错误正在破坏主机矩阵上的指针数组,这会在您尝试打印结果时导致seg错误
  • 您传递给的参数不太正确。对于
    宽度
    高度
    参数,您传递的是
    siz
    ,它是以字节为单位的矩阵维度。但是您应该只传递
    宽度
    参数的字节维度。对于
    高度
    参数,您应该传递行数,即你的情况下为4。打电话到cudaMemcpy2D时有类似的要求,但你的要求是正确的
  • 现在让我们看一下您的内核。在调用中,您将启动一个由16个线程组成的网格。因为您的矩阵有16个元素,这似乎是合理的。这意味着一种线程策略,其中每个线程将负责结果的一个元素。但是查看内核代码,您让每个线程计算结果有两种方法可以解决这个问题:要么将网格减少到4个线程,而不是16个线程(从代码修改的角度来看,可能更简单),要么重新编写内核(消除for循环),让每个线程计算一个输出元素(这可能会同时做更多的工作)
  • 此外,在内核中,在基于指针算术的索引中使用
    pitch
    参数。但是请记住,pitch是以字节为单位的,对于指针算术索引,编译器希望参数以元素为单位-它根据数据类型为您进行字节转换。同样,这实际上是一个C问题,一个nd不特定于CUDA。您可以通过在内核中使用
    pitch
    的任何位置使用
    (pitch/sizeof(int))
    来修复此问题
  • 您正在将音调的
    siz
    传递给内核。您应该将音调参数的
    pitch
    传递给内核。
    siz
    实际上是“音调”在主机数据存储上,但
    pitch
    是设备上存储的节距。内核在设备存储上运行,因此需要正确的节距
  • 建议对所有CUDAAPI调用和内核调用执行此操作
  • 以下是一些以某种方式解决上述所有问题的代码:

    #include<stdio.h>
    #define siz (4*sizeof(int))
    
    #define cudaCheckErrors(msg) \
        do { \
            cudaError_t __err = cudaGetLastError(); \
            if (__err != cudaSuccess) { \
                fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                    msg, cudaGetErrorString(__err), \
                    __FILE__, __LINE__); \
                fprintf(stderr, "*** FAILED - ABORTING\n"); \
                exit(1); \
            } \
        } while (0)
    
    __global__ void addmatrix(int *m1,int *m2,size_t pitch)
    {
        int r=threadIdx.x;
        int *r1=m1+r*(pitch/sizeof(int));
        int *r2=m2+r*(pitch/sizeof(int));
        int c;
        for(c=0;c<4;c++)
        {
            r1[c]+=r2[c];
        }
    }
    int main()
    {
        int i,j;
        int *m1_c,*m2_c;
        int *m1_d,*m2_d;
        size_t pitch;
        cudaError_t err;
        m1_c=(int *)malloc(16*sizeof(int));
        m2_c=(int *)malloc(16*sizeof(int));
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                m1_c[(i*4)+j]=rand()%10;
                m2_c[(i*4)+j]=rand()%10;
            }
        }
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                printf("%d\t",m1_c[(i*4)+j]);
            }
            printf("\n");
        }
        printf("\n\n");
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                printf("%d\t",m2_c[(i*4)+j]);
            }
            printf("\n");
        }
        err=cudaMallocPitch((void **)&m1_d,&pitch,siz,4);
        cudaCheckErrors("cm1");
        err=cudaMallocPitch((void **)&m2_d,&pitch,siz,4);
        cudaCheckErrors("cm2");
        err=cudaMemcpy2D(m1_d,pitch,m1_c,siz,siz,4,cudaMemcpyHostToDevice);
        cudaCheckErrors("cm3");
        err=cudaMemcpy2D(m2_d,pitch,m2_c,siz,siz,4,cudaMemcpyHostToDevice);
        cudaCheckErrors("cm4");
        dim3 grid(1);
        dim3 block(4);
        addmatrix<<<grid,block>>>(m1_d,m2_d,pitch);
        cudaMemcpy2D(m1_c,siz,m1_d,pitch,siz,4,cudaMemcpyDeviceToHost);
        cudaCheckErrors("cm5");
    
        for(i=0;i<4;i++)
        {
            for(j=0;j<4;j++)
            {
                printf("%d\t",m1_c[(i*4)+j]);
            }
            printf("\n");
        }
        err=cudaFree(m1_d);
        err=cudaFree(m2_d);
        err=cudaDeviceReset();
    }
    
    #包括
    #定义大小(4*sizeof(int))
    #定义cudaCheckErrors(msg)\
    做{\
    cudaError\u t\u err=cudaGetLastError()\
    如果(_err!=cudaSuccess){\
    fprintf(标准,“致命错误:%s(%s位于%s:%d)\n”\
    msg,cudaGetErrorString(_err)\
    __文件(行)\
    fprintf(stderr,“***失败-中止\n”)\
    出口(1)\
    } \
    }而(0)
    __全局无效添加矩阵(int*m1,int*m2,大小\u t间距)
    {
    int r=threadIdx.x;
    int*r1=m1+r*(螺距/尺寸(int));
    int*r2=m2+r*(螺距/尺寸(int));
    INTC;
    
    对于(c=0;c)您是否可以包括您得到的错误?如果您需要帮助解决您的问题,您必须对您的问题提供更好的描述。“无法正确获得输出”没有足够的信息来帮助你。到底发生了什么?你认为应该发生什么?你为什么不检查每个CUDA API函数的返回值?你使用的是什么CUDA版本、GPU和操作系统?在回答你的问题之前,有些人需要知道好的答案代码中至少有两个问题。无法将指向2D数组的指针传递给cudaMemcpy2D。您应该了解它所需的参数及其类型。对于cudaMemcpy2D,两个指针都是指向内存的指针,但您传递的是一个指向内存的指针和一个指向内存的指针。第二个问题是,所有数组都是indexing从1开始,而不是从0开始。也许你不了解C数组索引的基本知识。哎呀,我真的希望你能为此获得报酬!谢谢你,罗伯特·克罗维拉先生。我有一些想法可以做到这一点。但我仍然无法修复分段错误。