Kopiowanie danych z CPU do GPU [C - CUDA]

Odpowiedz Nowy wątek
2015-01-22 20:25
0

Witam serdecznie. Mam do wykonania taki o to projekt. Wykonać efekt rozmycia (Blur) na bitmapie na CPU i GPU i porównać szybkość wykonanego algorytmu. Tak jak na CPU mi to działa tak na GPU już nie. Nie wiem dlaczego ale dane odczytane przez CPU z obrazka nie są kopiowane do GPU poprzez funkcję cudaMemcpy. Wstawiam poniżej kod który wykonałem (drobna uwaga, funkcja GPUBlur nie jest jeszcze zrobiona bo szukam pomysłu na jej wykonanie).

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

using namespace std;

BITMAPFILEHEADER BMPH; // 14 bajtowy nagłówek pliku bitmapy
BITMAPINFOHEADER BMPINFOH; // Zawiera informacje na temat wymiarów i kolorów w formacie DIB

// Wczytywanie nagłówka pliku
void ReadFileHeader()
{
    char *filename = "birds.bmp";
    FILE *input = fopen(filename, "rb+");

    if (input == NULL)
    {
        printf("- Plik nie zostal otwarty (Wczytywanie naglowka pliku)\n");
        exit(0);
    }
        printf("- Plik zostal otwarty pomyslnie (Wczytywanie naglowka pliku)\n");

    if (fread(&BMPH, sizeof(BITMAPFILEHEADER), 1, input) != 1) { 
        printf(" Blad w odczycie naglowka bmp\n");
    }

    if (fread(&BMPINFOH, sizeof(BITMAPINFOHEADER), 1, input) != 1) {
        printf(" Blad w odczycie informacji o zdjeciu\n");
    }
    fclose(input);

}

// Pobieranie wartosci RGB do tablicy
void Read_RGB_Array(unsigned char buffer[])
{
    unsigned long int n = BMPINFOH.biWidth*BMPINFOH.biHeight * 3; 
    char *filename = "birds.bmp";
    FILE *input = fopen(filename, "rb+");

    fseek(input, BMPH.bfOffBits, SEEK_SET); 

    for (int i = 0; i<n; i++)
    {
        buffer[i] = fgetc(input);   
    }
    printf("- Odczytano pomyslnie zawartosc danych o obrazie i zapisano do tablicy na CPU\n");
    fclose(input);
}

__global__ void GPUBlur(unsigned char buffer[])
{

    int yi = 512, xi = 768;

    //int x = threadIdx.x + blockIdx.x * blockDim.x;
    //int y = threadIdx.y + blockIdx.y * blockDim.y;

    for (int y = 1; y < yi - 1; y++) {
        for (int x = 0; x < xi - 2; x++) {
            for (int c = 0; c < 3; c++) {

 buffer[((y*xi * 3) + (x * 3 + 3)) + c] =
(buffer[(((y - 1)*xi * 3) + (x * 3)) + c] + buffer[(((y - 1)*xi * 3) + (x * 3 + 3)) + c] + buffer[(((y - 1)*xi * 3) + (x * 3 + 6)) + c] +
 buffer[((y*xi * 3) + (x * 3)) + c] + buffer[((y*xi * 3) + (x * 3 + 3)) + c] + buffer[((y*xi * 3) + (x * 3 + 6)) + c] +
 buffer[(((y + 1)*xi * 3) + (x * 3)) + c] + buffer[(((y + 1)*xi * 3) + (x * 3 + 3)) + c] + buffer[(((y + 1)*xi * 3) + (x * 3 + 6)) + c]) / 9;

            }
        }
    }
}

void WriteBMP(unsigned char buffer[])
{
    char *filename = "birds_BLUR.bmp";
    FILE *output = fopen(filename, "wb+");

    if (output == NULL)
    {
        printf("- Plik nie zostal otwarty (Zapisywanie bitmapy do pliku)\n");
        exit(0);
    }
        printf("- Plik zostal otwarty pomyslnie (Zapisywanie bitmapy do pliku)\n");

    // Zapis nagłówka
    fwrite(&BMPH, 1, sizeof(BMPH), output); 
    // Zapis informacji o pliku
    fwrite(&BMPINFOH, sizeof(BMPINFOH), 1, output);
    // Zapisuje dane obrazu
    fwrite(buffer, 1, BMPINFOH.biWidth*BMPINFOH.biHeight * 3, output);

    fclose(output);

}

int main()
{

    int start = GetTickCount(); // Pobiera aktualny czas

    ReadFileHeader();

    unsigned char *buffer_cuda;
    cudaMalloc((void**)&buffer_cuda, BMPINFOH.biWidth*BMPINFOH.biHeight * 3); 

    unsigned char *buffer = (unsigned char*) malloc(BMPINFOH.biWidth*BMPINFOH.biHeight * 3); 

    Read_RGB_Array(buffer); 

    cudaMemcpy(buffer_cuda, buffer, BMPINFOH.biWidth*BMPINFOH.biHeight * 3, cudaMemcpyHostToDevice); // Kopiowanie danych CPU --> GPU

    GPUBlur<<<BMPINFOH.biWidth*BMPINFOH.biHeight * 3, 1>>> (buffer); 

    cudaMemcpy(buffer, buffer_cuda, BMPINFOH.biWidth*BMPINFOH.biHeight * 3, cudaMemcpyDeviceToHost);

    WriteBMP(buffer); 

    cudaFree(buffer_cuda); 
    free(buffer); 

    cout << "Czas wykonania kodu aplikacji: " << GetTickCount() - start << "ms." << endl;
    system("pause");
}
edytowany 1x, ostatnio: Se-BASS-tian, 2015-01-22 20:30

Pozostało 580 znaków

2015-01-22 20:48
0

Sprawdź jaki błąd zwraca cudaMemcpy: http://docs.nvidia.com/cuda/cuda-runtime-api/groupCUDARTTYPES.html#groupCUDARTTYPES_1g3f51e3575c2178246db0a94a430e0038

Pozostało 580 znaków

2015-01-22 20:56
0

Chodzi o to że jak ustawię breakpoint na linii

 GPUBlur<<<BMPINFOH.biWidth*BMPINFOH.biHeight * 3, 1>>> (buffer); 

to podczas debuggowania w okienku Locals/Autos dla buffer_cuda pokazuje wartość: "buffer_cuda 0x406e0000 < Error reading characters of string. > ".

edytowany 2x, ostatnio: Se-BASS-tian, 2015-01-22 20:58

Pozostało 580 znaków

2015-01-22 21:06
0

Nie możesz debugować kernel code "zwykłym" debuggerem. Zainstaluj Parallel Nsight.
Poza tym definiuj poprawniej problemy, bo napisałeś, że cudaMemcpy ci nie działa a wychodzi na to, że po prostu nie wiesz jak debugować kernel code.

Pozostało 580 znaków

2015-01-22 21:19
0

Posiadam NSight. Dokonałem "Start CUDA Debugging" ustawiając pułapkę na tej samej linii. Pokazuje się jakiś błąd na breakpoincie: "The breakpoint will not currently be hit. No CUDA device code is associated with line 83 - EOF". Komunikat ten wyświetla się po najechaniu myszką na breakpoint.

Pozostało 580 znaków

2015-01-22 21:31
0

Sprawdź czy w opcjach masz włączone generowanie danych debuggera GPU. Sprawdź czy w katalogu z exe masz pliki .pdb i .ilk. I najważniejsze sprawdź czy kompilujesz kod z tym samym compute capability, jaki ma twoja karta z cuda.

Pozostało 580 znaków

2015-01-22 22:20
0

Chyba nie wiem gdzie sprawdzić w opcjach czy jest włączone generowanie danych debuggera GPU :/ . Jeżeli chodzi o pliki .pdb i .ilk to są w katalogu w którym znajduje się plik *.exe. Moja karata GTX660M posiada Compute Capability: 3.0. Dobrze patrzę na opcję by sprawdzić czy kompiluje się na tym samym Compute Capability ? : Projekt ->Właściwości Nazwa_Projektu -> CUDA C/C++ -> Device -> Code Generation: compute_20, sm_20 ?

Pozostało 580 znaków

2015-01-23 20:13
0

W takim razie spróbuj ustawić compute capability na compute_30,sm_30.

Pozostało 580 znaków

2015-01-23 20:27
0

compute capability zmienione na compute_30,sm_30. Mimo wszystko po wykonaniu "Start CUDA debugging" na NSIGHT nadal pojawia się to samo ostrzeżenie na breakpoincie. Nie debuggowałem nigdy kernel code (pierwszy jakikolwiek projekt związany z CUDA) i nie mam pomysłów jak sprawić bym w końcu mógł sprawdzić czy dane są skopiowane do zaalokowanej pamięci na GPU.

Pozostało 580 znaków

2015-01-23 20:34
0

No a jak postawisz breakpoint w metodzie kernela i spróbujesz tam zdereferować pointer? Jeśli nie poleci segfault to znaczy, że działa. (Przy okazji sprawdzisz, czy nsight ci działa).

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0