Cuda Basic Program (Запись значений в матрицу и std: cout не работает); Основная функция не запускается - PullRequest
0 голосов
/ 18 сентября 2018

Я написал довольно простую программу Cuda. Я хотел бы присвоить значения матрице в памяти устройства. Затем я хочу скопировать значения на хост и отобразить их. Программа, которую я написал, не работает. Но я не знаю почему. Я пытался выяснить, что я делаю неправильно, отображая состояние с помощью cout, но даже это не работает, поэтому я думаю, что основная функция не запускается.

Кто-нибудь знает в чем проблема?

Вот мой код:

    #include "cuda_runtime.h"
    #include "device_launch_parameters.h"
    #include <iostream>
    #include <stdio.h>
    const int N = 1024;


    __global__ void matrix(float *d_A)
    {
        int col = blockIdx.x * blockDim.x + threadIdx.x;
        int row = blockIdx.y * blockDim.y + threadIdx.y;


        int index = col + row * N;
        if (col < N && row < N)
        {
            d_A[index] = 255;
        }
    }
    int main()
    {
        std::cout << "Programm begins";
        float A[N * N];
        float d_A[N * N];

        cudaMalloc((void**)&d_A, (N * N)*sizeof(float));
        std::cout << "Matrizes allocated";
        std::cout << A[0] << " , " << A[1] << " , " << A[2] << " , " << A[3] << " , " << A[4] << " , " << A[5] << "\n";
        std::cout << A[1024] << " , " << A[1025] << " , " << A[1026] << " , " << A[1027] << " , " << A[1028] << " , " << A[1029] << "\n";
        matrix << <1024, 1024 >> >(d_A);
        std::cout << "Wrote Matrix to local device memory";
        std::cout << d_A[0] << " , " << d_A[1] << " , " << d_A[2] << " , " << d_A[3] << " , " << d_A[4] << " , " << d_A[5] << "\n";
        std::cout << d_A[1024] << " , " << d_A[1025] << " , " << d_A[1026] << " , " << d_A[1027] << " , " << d_A[1028] << " , " << d_A[1029] << "\n";


        cudaMemcpy(A, d_A, N * N * sizeof(float), cudaMemcpyDeviceToHost);
        std::cout << "Wrote Matrix to host memory";
        std::cout << A[0] << " , " << A[1] << " , " << A[2] << " , " << A[3] << " , " << A[4] << " , " << A[5] << "\n";
        std::cout << A[1024] << " , " << A[1025] << " , " << A[1026] << " , " << A[1027] << " , " << A[1028] << " , " << A[1029] << "\n";

        return 0;
    }

Ответы [ 2 ]

0 голосов
/ 18 сентября 2018

Есть несколько проблем с предоставленным вами кодом.

  1. Разыменование памяти устройства с хоста, например d_A[0] недопустимо и приведет к неопределенному поведению.
  2. Обработка данных как двумерных внутри ядра, тогда как сетка и блок представляются как одномерные. В этом случае переменная row всегда будет равна 0 и, по сути, не будет играть никакой роли при вычислении index. Определите размеры сетки и блока как тип dim3 для создания 2D-сетки и блока.
  3. Не рекомендуется создавать в стеке массивы большого размера, такие как float A[N*N];. Предпочитайте динамическое выделение памяти с оператором new.
  4. Распределение памяти устройства для уже выделенного массива хоста d_A - неопределенное поведение. Если вы хотите выделить память устройства для переменной, просто объявите ее как простой указатель, такой как float* d_A;.

Фиксированный код может выглядеть так:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h>
const int N = 1024;

__global__ void matrix(float *d_A)
{
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    int row = blockIdx.y * blockDim.y + threadIdx.y;


    int index = col + row * N;
    if (col < N && row < N)
    {
        d_A[index] = 255;
    }
}
int main()
{
    std::cout << "Programm begins"<<std::endl;
    float *A = new float[N*N];
    float *d_A;

    cudaMalloc((void**)&d_A, (N * N)*sizeof(float));
    std::cout << "Matrizes allocated"<<std::endl;
    std::cout << A[0] << " , " << A[1] << " , " << A[2] << " , " << A[3] << " , " << A[4] << " , " << A[5] <<std::endl;
    std::cout << A[1024] << " , " << A[1025] << " , " << A[1026] << " , " << A[1027] << " , " << A[1028] << " , " << A[1029] <<std::endl;

    dim3 block(32,32);
    dim3 grid;
    grid.x = (N + block.x - 1) / block.x;
    grid.y = (N + block.y - 1) / block.y;

    matrix << <grid, block >> >(d_A);
    std::cout << "Wrote Matrix to local device memory"<<std::endl;

    cudaMemcpy(A, d_A, N * N * sizeof(float), cudaMemcpyDeviceToHost);
    std::cout << "Wrote Matrix to host memory"<<std::endl;
    std::cout << A[0] << " , " << A[1] << " , " << A[2] << " , " << A[3] << " , " << A[4] << " , " << A[5] <<std::endl;
    std::cout << A[1024] << " , " << A[1025] << " , " << A[1026] << " , " << A[1027] << " , " << A[1028] << " , " << A[1029] <<std::endl;

    cudaFree(d_A);
    delete[] A;

    return 0;
}

Настоятельно рекомендуется добавить проверку ошибок для каждого вызова API CUDA, чтобы упростить процесс отладки.

0 голосов
/ 18 сентября 2018

Есть несколько проблем с вашим кодом, я бы упростил код еще больше, если это ваши первые шаги в Cuda и C ++. Попробуйте это (важные изменения в окружении звезд комментария);

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <iostream>
#include <stdio.h>

const int Grids = 256;
const int Threads = 256;

__global__ void matrix(float *d_A)
{
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    d_A[idx] = 1.0;
}

int main()
{
    std::cout << "Programm begins";

    // ****
    float *A = new float[Grids * Threads];
    float *d_A;
    // ****

    cudaMalloc((void**)&d_A, (Grids * Threads)*sizeof(float));

    matrix<<<Grids, Threads>>>(d_A);

    cudaMemcpy(A, d_A, Grids * Threads*sizeof(float), cudaMemcpyDeviceToHost);

    for(int i=0; i < (Grids * Threads); ++i)
    {
         cout << A[i] << ",";
    }

    // ****
    cudaFree(d_A);
    delete A;
    // ****  

    return 0;
}

Также посмотрите основные примеры, https://devblogs.nvidia.com/easy-introduction-cuda-c-and-c/

Несколько вопросов здесь;

1) Объем выделяемой памяти хоста N * N (1024 * 1024) большой и может быть недоступен из кучи

2) Когда вы объявили переменную d_A, вы также объявили память хоста и память устройства для нее, что не требуется

3) Вы не освободили память устройства для d_A

4) Возможно, ваше устройство / графический процессор не поддерживает одновременную работу 1024 потоков; в этом случае это может произойти сбой в молчании, и в результате ваше ядро ​​не будет работать.

...