Ошибка обработки изображения CUDA

Я работаю над небольшим проектом обработки изображений. Я хочу запустить программу CUDA, которая выполняет вычитание изображений. Итак, у вас есть фон изображения и изображение с тем же фоном, но с некоторыми другими вещами на нем. Как только вы вычитаете изображения, вы получите то, что осталось. Оба изображения имеют размер 480 * 360, а мой графический процессор - GTX780. Моя программа выдает ошибку ./main': free(): invalid next size (normal): 0x000000000126bd70 *** Aborted (core dumped), и выходное изображение неверно. Я ломал голову, чтобы решить эту проблему. Вот код:

Ядро:

__global__ void add(unsigned char* a, unsigned char* b, unsigned char* c, int numCols, int numWidth) {
    int i = blockIdx.x * blockDim.x + threadIdx.x; //Column
    int j = blockIdx.y * blockDim.y + threadIdx.y; //Row
    if(i < numWidth && j < numCols)
    {
      int idx = j * numCols + i;
      c[idx] = b[idx] - a[idx];
    }   
}

и основная функция:

int main() {
    CImg<unsigned char> img1("1.bmp");
    CImg<unsigned char> img2("2.bmp");
    //both images have the same size
    int width = img1.width();
    int height = img1.height();

    int size = width * height * 3; //both images of same size

    dim3 blockSize(16, 16, 1);
    dim3 gridSize((width + blockSize.x - 1) / blockSize.x, (height + blockSize.y - 1) / blockSize.y, 1);

    unsigned char *dev_a, *dev_b, *dev_c;

    cudaMalloc((void**)&dev_a, size * (sizeof(unsigned char)));
    cudaMalloc((void**)&dev_b, size * (sizeof(unsigned char)));
    cudaMalloc((void**)&dev_c, size * (sizeof(unsigned char)));

    cudaMemcpy(dev_a, img1, size * (sizeof(unsigned char)), cudaMemcpyHostToDevice);
    cudaMemcpy(dev_b, img2, size * (sizeof(unsigned char)), cudaMemcpyHostToDevice);

    add<<<gridSize, blockSize>>>(dev_a, dev_b, dev_c, height, width);

    cudaMemcpy(img2, dev_c, size * (sizeof(unsigned char)), cudaMemcpyDeviceToHost);

    img2.save("out.bmp");
    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);
    return 0;
}

Изображение загружается с библиотекой CImg.


person KostasRim    schedule 31.03.2016    source источник
comment
Строка int idx = j * numCols + i;, которой предшествует j<numCols, выглядит подозрительно. Если j является вашим индексом столбца, вам лучше использовать int idx = i * numCols + j;.   -  person Peter Barmettler    schedule 01.04.2016
comment
@mman нет, это для устройства. Если бы он был на хосте, это был бы обычный malloc или новый. Проблема в байтах, я думаю, что как-то выделяется меньше байтов   -  person KostasRim    schedule 01.04.2016
comment
Это не приведет к сбою вашей программы, но либо вы находите в 3 раза больше необходимой памяти, либо вычисляете только треть (вы используете size = width * height * 3, а затем передаете ширину и высоту как numWidth и numHeight.)   -  person Elijan9    schedule 01.04.2016
comment
Каков размер img1? Я имею в виду размер?   -  person mantlabs    schedule 01.04.2016
comment
@mman sizeof(imga1) равно 32, но потому что это указатель шаблона.   -  person KostasRim    schedule 01.04.2016
comment
Разве вы не должны использовать img1.data() вместо img1 и img2.data() вместо img2 в cudaMemcpy операциях? похоже, как извлекается указатель на базовые данные: адрес этого буфера памяти может быть получен функцией CImg‹T›::data().   -  person Robert Crovella    schedule 01.04.2016
comment
@RobertCrovella, позвольте мне проверить это, спасибо   -  person KostasRim    schedule 01.04.2016
comment
@RobertCrovella Да, вы были правы! Я понятия не имею, как Cimg распределяет память. Забавно, что когда я определил указатели как int, я получил тот же правильный результат, что и при передаче в качестве параметра img1.data(). По какой-то причине Cimg() выделяет дополнительные байты за сценой. Хотя я понятия не имею, почему он это делает. Еще раз спасибо   -  person KostasRim    schedule 03.04.2016
comment
@mman да :) Cimg делает некоторые распределения за кулисами. Пришлось проверить документацию.   -  person KostasRim    schedule 03.04.2016
comment
@KostasRim: было бы полезно, если бы вы могли принять вики-ответ сообщества, который я добавил, чтобы этот вопрос выпал из очереди без ответа для тега CUDA   -  person talonmies    schedule 24.03.2017
comment
@talonmies вот ты где.   -  person KostasRim    schedule 31.03.2017
comment
@KostasRim: спасибо за помощь   -  person talonmies    schedule 31.03.2017


Ответы (1)


Проблема заключалась в некорректном использовании контейнеров cimg в коде хоста. Согласно документации, доступ к указателю данных изображения осуществляется с помощью метода data(), что означает, что cudaMemcpy вызовы в коде хоста должны быть снабжены img1.data() и img2.data().

[этот ответ был собран из комментариев и добавлен как запись в вики сообщества]

person Community    schedule 25.12.2016