LINUX.ORG.RU

[cuda] [ночь] Я туплю или так и должно быть?

 


0

1

Просьба к владельцам видеокарт от nvidia (любых) и cuda-sdk - скомпилировать и запустить нижеуказанный код.

Ничего вредоносного там нет :-P это не скрипт на перле. По замыслу он должен инициализировать трёхмерный массив числами от 0 до 78*78*78-1. Только ни хрена не получается, ничего не работает.

Если использовать одномерные или двумерные гриды и блоки, то вроде работает (только не так удобно работать с трёхмерными массивами), а вот так - засада какая-то. Или может я на ночь глядя опечатку в коде допустил?

Разумеется, мне не это нужно - а более серьёзная вычислительная задача - только там такие же болты, долго думал, где ошибка, а оказывается, он и с такой простой тестовой задачей не справляется. %) Или может, это хардварная проблема, видеокарта не поддерживает такое? Вообще странно.

Просьба нижайшая - запустите, и скажите, что выведет (всё постить необязательно, в двух словах - работает или нет)

Кастую в тред Reset, Eddy_Em, vertexua, плохо помню, кто ещё в этой матчасти разбирается... И необязательно разбираться - просто скомпильте и запустите ;) и скажите. что получится.

#include <iostream>

#define BLOCK_SIZE 8
#define ARRAY_SIZE 78

__global__ void testKernel(float *data) {
    int ix = blockIdx.x * blockDim.x + threadIdx.x;
    int iy = blockIdx.y * blockDim.y + threadIdx.y;
    int iz = blockIdx.z * blockDim.z + threadIdx.z;
    if (ix > ARRAY_SIZE) return;
    if (iy > ARRAY_SIZE) return;
    if (iz > ARRAY_SIZE) return;
    
    int index = ix+iy*ARRAY_SIZE+iz*ARRAY_SIZE*ARRAY_SIZE;
    data[index] = index;
}

int main(int argc, char *argv[]) {
    int size = ARRAY_SIZE*ARRAY_SIZE*ARRAY_SIZE;
    float *devData = NULL;
    float *outData = new float[size];
    
    for (int i=0; i!=size; i++) {
	outData[i] = 0 ;
    }
    
    cudaMalloc((void**)&devData,size*sizeof(float));
    
    dim3 blockSize(BLOCK_SIZE,BLOCK_SIZE,BLOCK_SIZE);
    dim3 gridSize(ARRAY_SIZE/BLOCK_SIZE+1,ARRAY_SIZE/BLOCK_SIZE+1,ARRAY_SIZE/BLOCK_SIZE+1);
    
    testKernel<<<gridSize,blockSize>>>(devData);

    cudaMemcpy(outData,devData,sizeof(float)*size,cudaMemcpyDeviceToHost);
    
    for (int i=0; i!=size; i++) {
	std::cout << outData[i] << std::endl;
    }
    
    cudaFree(devData);
    delete[] outData;
  
    return 0;
}
Ответ на: комментарий от BattleCoder

Ну тогда вэлкам ту зе консоль.
Это конечно неприятно, но по мне и так хорошо, что можно параллельно с иксами пускать свои программы.

b_a
()
Ответ на: комментарий от jtootf

Догадался таки я добавить после запуска ядра строки:

cudaError_t error = cudaGetLastError();
if (error!=cudaSuccess) {
    std::cerr << "Error " << error << ": " << cudaGetErrorString(error) << std::endl;
}

И таки понял, в чём ошибка.

Error 7: too many resources requested for launch

Вот такую ошибку я получаю... Если я правильно понимаю, она возникает либо когда слишком много shared-памяти использую, либо когда много регистров. Либо, если слишком большой размер блока/грида. С размерами блока и грида всё нормально - склоняюсь к тому, что слишком много регистров.

Как бы их правильнее посчитать? Ведь логики никакой - переменные «float tmp1 = devConstant1 и float tmp2 = devConstant2;» нормально присваиваются... потом первой я присваиваю синус, всё нормально. А если от второй тоже считаю синус - то fail. Как подсчёт синуса связан с количеством регистров??? я ведь даже память дополнительную под это не выделяю...

И странно, что у меня возникает такая ошибка, а у вас не возникает. %) Я сегодня вечером ещё немного пошаманю с этим - попробую разобраться, мб. выложу какой-нить код и попрошу его запустить (на выходе он должен либо выдать ok, либо номер и текст ошибки), если несложно, конечно. :)

BattleCoder ★★★★★
() автор топика
Ответ на: комментарий от b_a

Отладчик мне по идее не нужен... банально иногда нужно запускать cudaGetLastError() :)

После кодинга на java очень непривычно на этом чистом C кодить... Там исключения сами выбрасываются, их осталось только перехватить, и в логгер записать =) и ты практически знаешь, в чём ошибка, вот так:

try {
    blah-blah-blah
    ...
} catch (Exception e) {
    logger.error(e.getMessage());
    throw new RuntimeException(e);
} finally {
    blah-blah-blah
}

Наверное, жаба людей портит, да :)

BattleCoder ★★★★★
() автор топика
Ответ на: комментарий от BattleCoder

Советую перед запуском программы делать инициализацию, в которой узнавать, что за видеокарта, каков допустимый объем памяти и т.п.

А ресурсы выделять, исходя из констант, которые и будут устанавливаться функцией-инициализатором.

Да, еще: в отличие от «обычной» оперативки, оперативка видеокарты ядром автоматом не подчищается, поэтому если у вас течет память, то это может привести к разным неприятным последствиям и трата ресурсов впустую - еще цветочки. Помню, у меня, когда я начинал эксперименты с CUDA, раз в полчаса компьютер подвисал и/или по экрану начинали «ползать» всякие артефакты.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

И еще: всякие аллокаторы советую сразу же оформлять в макросы, чтобы «автоматом» ошибки проверять.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Я смотрел выхлоп deviceQuery. Регистров 8 килобайт, разделяемой памяти 16 килобайт. Должно хватать.

Ну а глобальной памяти так вообще 512 мегабайт... понятно, что её _не_всю_ можно использовать, но всё равно должно быть достаточно.

И еще: всякие аллокаторы советую сразу же оформлять в макросы, чтобы «автоматом» ошибки проверять.

Надо всё-таки осилить до конца Кернигана и Ритчи. :( Всё времени никак нет. Попробую... Макросами никогда не пользовался, оборачивал всегда всё в функции.

Наверное, так удобнее будет, да.

Помню, у меня, когда я начинал эксперименты с CUDA, раз в полчаса компьютер подвисал и/или по экрану начинали «ползать» всякие артефакты.

Забавно. :) Я никаких артефактов пока не видел. Может быть - это на старых версиях CUDA такое только было? Или от этого не зависит...

BattleCoder ★★★★★
() автор топика
Ответ на: комментарий от BattleCoder

Я никаких артефактов пока не видел.

Попробуйте сделать то, что в обычных условиях оканчивается сегфолтом. В случае с CUDA никаких сегфолтов не будет, но начнутся всякие «приколы».

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от BattleCoder

Просто не нужно воспринимать видеокарту как компьютер. Нужно относится к ней как к специализированному матричному процессору.

b_a
()
Ответ на: комментарий от b_a

Ну тут вообще о другом речь... это CUDA Runtime API такой... его можно было так написать, можно было по-другому =) короче, не суть. Главное, работает...

Сейчас вот продолжаю разбираться со своими проблемами... Ошибку 7 больше не пишет (уменьшил число блока), запускаю другую из своих программ - вижу резкую «вспышку» на экране (никаких артефактов), и все значения, которые я вывожу, равны нулю - то ли ядро не срабатывает, то ли memcpy, пока непонятно.

Да, и это происходит очень _быстро_. Следовательно, вычисления где-то попросту прерываются.

BattleCoder ★★★★★
() автор топика
Ответ на: комментарий от BattleCoder

Может быть - компиз и прочие радости запущены ? У меня ваш код отрабатывал нормально. У меня в качестве wm - fluxbox. Больше никаких рюшек.
Артефакты на экране наблюдал после продолжительной работы своей программы и когда она требовала почти всю память на карте. Возможно следует посмотреть сколько памяти доступно cuMemGetInfo ?
Ну и как совет - все таки прогнать программу под cuda-gdb. Возможно что то всплывет.

b_a
()
Ответ на: комментарий от b_a

compiz нет. kwin с эффектами. Слушайте, вы мне подсказали очень важную мысль... спасибо. попробую отключить. Даже в голову бы не пришло. =)

Памяти (глобальной) требует она немного (в районе может двух мегабайт, может, больше, я не подсчитывал)... вот регистров или локальной памяти может и не хватить, хотя даже это странно.

BattleCoder ★★★★★
() автор топика

Как же тяжело разбираться даже в своём собственном коде когда прошла неделя или две. %( Ничего не могу с этим поделаться - времени вообще ни на что не хватает... вот и руки до этого не доходят (а это ж дипломная). ужас, словом. Неужели пол-лора также диссертации в последний момент готовят? :(

Ладно, это было небольшое лирическое отступление.

Обернув memcpy в обработчик ошибок - получаю, что после второго memcpy (который, в общем, запускается уже ПОСЛЕ запуска ядра, который и копирует РЕЗУЛЬТАТ обратно) - получаю ошибку номер 4 «unspecified launch failure».

Пожалуй. и правда, надо обернуть эти функции в макросы... так удобнее будет.

И ни хрена непонятно из-за чего это может возникать. Кстати, запуск ядра возвращает cudaSuccess - то есть отрабатывает без ошибок, специально проверял.

(полный код приводить не буду и не хочу, его слишком много, лучше в порядок приведу).

Наверное, плюну я на эту трёхмерную иерархию нитей, и попробую с одномерной... посмотрю, что получится. Осталось только решить - 256 нитей или 512... на блок.

BattleCoder ★★★★★
() автор топика
Ответ на: комментарий от BattleCoder

Первое, что нашла нигма - http://www.herikstad.net/2009/05/cuda-unspecified-launch-failure.html

Вообще говоря, я действительно использую shared-memory, без этого мне никак просуммировать все значения... только не пойму пока, почему неправильно.

Если приведу свой код в порядок, выложу сюда. %) Хотя там вроде итак всё правильно.

BattleCoder ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.