【问题标题】:CUDA: Matrix + Matrix, segmentation fault when printing solution matrix in hostCUDA:Matrix + Matrix,在主机中打印解决方案矩阵时出现分段错误
【发布时间】:2019-05-31 22:32:30
【问题描述】:

我正在尝试在 CUDA 中将一个矩阵添加到另一个矩阵的简单操作,但是当我尝试检查结果时出现分段错误,这是代码:

/* Includes, system */
#include <stdio.h>

#include <cuda.h>
#include <cuda_runtime.h>
#define N 15000

/* DEVICE CODE */
__global__ void sumaMatrices(int *d_matrix1, int *d_matrix2, int *d_matrixSolucion){

    int idThread = blockIdx.x*blockDim.x + threadIdx.x;

    if (idThread < N)
    {
        d_matrixSolucion[idThread] = d_matrix1[idThread] + d_matrix2[idThread];
    }
}

__host__ void printMatrix(int **matrix) 
{
    int i, j;
    //only 4 so the file is not too big
    for (i = 0; i < 4; i++) 
    {
        for (j = 0; j < 4; j++)
        {
            printf("%d", matrix[i][j]);
            printf("  ");
        }
        printf("\n");
    }
    printf("\n");
}

/* HOST CODE*/
int main(int argc, char** argv)
{
    int i;

    int **h_matrix1;
    int **h_matrix2;
    int **h_matrixSolucion;

    int *d_matrix1;
    int *d_matrix2;
    int *d_matrixSolucion;

    h_matrix1 = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrix1[i] = (int*)malloc(N * sizeof(int*));
    }

    h_matrix2 = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrix2[i] = (int*)malloc(N * sizeof(int*));
    }

    h_matrixSolucion = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrixSolucion[i] = (int*)malloc(N * sizeof(int*));
    }

    cudaMalloc((void**)& d_matrix1,N*N*sizeof(int));
    cudaMalloc((void**)& d_matrix2,N*N*sizeof(int));
    cudaMalloc((void**)& d_matrixSolucion,N*N*sizeof(int));

    fillMatrix(h_matrix1);
    fillMatrix(h_matrix2);
    fillMatrixTo0(h_matrixSolucion);

    for(i = 0; i < N; i++) 
    {
        cudaMemcpy(&d_matrix1[i*N], h_matrix1[i], N*sizeof(int), cudaMemcpyHostToDevice);
        cudaMemcpy(&d_matrix2[i*N], h_matrix2[i], N*sizeof(int), cudaMemcpyHostToDevice);
    }

    int tamBloque = 256;
    int tamGrid = N/tamBloque + 1;
    sumaMatrices<<<tamGrid, tamBloque>>>(d_matrix1, d_matrix2, d_matrixSolucion);

    //nos traemos la información del device
cudaThreadSynchronize();
for(i = 0; i < N; i++) 
{
    cudaMemcpy(h_matrixSolucion[i], &d_matrixSolucion[i*N],tamGrid*sizeof(h_matrixSolucion[0]),cudaMemcpyDeviceToHost);
}

    printMatrix(h_matrix1);
    printMatrix(h_matrix2);
    printMatrix(h_matrixSolucion);
}

如果我评论最后一行,程序不会给出任何错误。

我猜问题是我没有在内核中正确存储信息(这一行:d_matrixSolucion[idThread] = d_matrix1[idThread] + d_matrix2[idThread];)但我对 CUDA 和真不知道怎么解决。

编辑:现在我已经改变了从设备获取信息的方式,这就是正在打印的内容:

0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6

2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8

2 4 6 8
0 0 0 0
0 0 0 0
0 0 0 0

前2个矩阵是有信息的,另一个是解,但只有1行。

【问题讨论】:

  • 将结果复制回主机时需要为cudaMemcpy 操作循环,就像将数据复制到设备时需要循环一样。您的基础主机分配不保证是连续的。此外,fillMatrix 在您显示的代码中未定义;它不会编译。
  • “您的底层主机分配不保证是连续的”。这就是我只填写第一行的原因吗? fillMatrix 确实存在,我只是没有添加到问题的代码中,因为我认为它没有添加任何内容,只是一个用随机数填充矩阵的函数。顺便说一句,我添加了更多信息
  • 不,还有另一个问题导致只有第一行是正确的。看我的回答项目 4。而且我没有说“fillMatrix 不存在”,我说“fillMatrix 在您显示的代码中未定义”,这是一个准确的说法。当要求对 SO 进行调试帮助时,您应该提供 minimal reproducible example,而 C(完整)表示当您发布 minimal reproducible example 时不应缺少 fillMatrix 之类的内容。无论如何,为什么不将其包含在您的帖子中?你已经有了它,它使我更容易处理你的代码。我其实想编译并运行你的代码。
  • 你是对的,对不起,我只是认为因为它是一个非常简单的功能,所以没有必要理解我遇到的问题,但我没有意识到没有它功能对于任何试图帮助我运行我的代码的人来说都会更难,再次抱歉。

标签: matrix cuda


【解决方案1】:

您的代码中存在各种错误。

  1. fillMatrix 没有定义
  2. 您使用malloc 执行的底层主机分配不能保证是连续的,因此您不能在单个cudaMemcpy 操作中将数据传回,但您必须使用循环,就像您用来将数据传输到的循环一样GPU
  3. 您的主机分配不完全正确,但它们不存在实际问题。这个:

    h_matrix1[i] = (int*)malloc(N * sizeof(int*));
    

    应该是这样的:

    h_matrix1[i] = (int*)malloc(N * sizeof(int));
    

    对于其他类似的实例也是如此。

  4. 您的网格(线程总数)大小不正确。您的内核使用一个线程来执行一个元素加法。因此,对于 NxN 矩阵,您需要 NxN 个线程,而不仅仅是创建和测试的 N 个线程。

以下代码已修复这些问题,并且对我来说似乎可以正常工作:

$ cat t2.cu
/* Includes, system */
#include <stdio.h>

#include <cuda.h>
#include <cuda_runtime.h>
#define N 15000

/* DEVICE CODE */
__global__ void sumaMatrices(int *d_matrix1, int *d_matrix2, int *d_matrixSolucion){

    int idThread = blockIdx.x*blockDim.x + threadIdx.x;

    if (idThread < N*N)
    {
        d_matrixSolucion[idThread] = d_matrix1[idThread] + d_matrix2[idThread];
    }
}

__host__ void printMatrix(int **matrix)
{
    int i, j;
    //only 4 so the file is not too big
    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            printf("%d", matrix[i][j]);
            printf("  ");
        }
        printf("\n");
    }
    printf("\n");
}

/* HOST CODE*/
int main(int argc, char** argv)
{
    int i;

    int **h_matrix1;
    int **h_matrix2;
    int **h_matrixSolucion;

    int *d_matrix1;
    int *d_matrix2;
    int *d_matrixSolucion;

    h_matrix1 = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrix1[i] = (int*)malloc(N * sizeof(int));
        for (int j = 0; j < N; j++) h_matrix1[i][j] = 1;
    }

    h_matrix2 = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrix2[i] = (int*)malloc(N * sizeof(int));
        for (int j = 0; j < N; j++) h_matrix2[i][j] = 2;
    }

    h_matrixSolucion = (int**)malloc(N * sizeof(int*));
    for (i = 0; i < N; i++)
    {
        h_matrixSolucion[i] = (int*)malloc(N * sizeof(int));
        for (int j = 0; j < N; j++) h_matrixSolucion[i][j] = 0;
    }

    cudaMalloc((void**)& d_matrix1,N*N*sizeof(int));
    cudaMalloc((void**)& d_matrix2,N*N*sizeof(int));
    cudaMalloc((void**)& d_matrixSolucion,N*N*sizeof(int));


    for(i = 0; i < N; i++)
    {
        cudaMemcpy(&d_matrix1[i*N], h_matrix1[i], N*sizeof(int), cudaMemcpyHostToDevice);
        cudaMemcpy(&d_matrix2[i*N], h_matrix2[i], N*sizeof(int), cudaMemcpyHostToDevice);
    }

    int tamBloque = 256;
    int tamGrid = (N*N)/tamBloque + 1;
    sumaMatrices<<<tamGrid, tamBloque>>>(d_matrix1, d_matrix2, d_matrixSolucion);

    cudaThreadSynchronize();
    for(i = 0; i < N; i++)
    {
        cudaMemcpy(h_matrixSolucion[i],&d_matrixSolucion[i*N],N*sizeof(int),cudaMemcpyDeviceToHost);
    }

    printMatrix(h_matrix1);
    printMatrix(h_matrix2);
    printMatrix(h_matrixSolucion);
}
$ nvcc -o t2 t2.cu
$ cuda-memcheck ./t2
========= CUDA-MEMCHECK
1  1  1  1
1  1  1  1
1  1  1  1
1  1  1  1

2  2  2  2
2  2  2  2
2  2  2  2
2  2  2  2

3  3  3  3
3  3  3  3
3  3  3  3
3  3  3  3

========= ERROR SUMMARY: 0 errors
$

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 2011-12-08
    相关资源
    最近更新 更多