Cuda char * присвоение переменной - PullRequest
2 голосов
/ 04 июля 2011

Это дополнительный вопрос к выбранному ответу в этом сообщении: Вывод программы cuda не соответствует ожидаемому .

Пока работают следующие функции:

__global__ void setVal(char **word)
{

    char *myWord = word[(blockIdx.y * gridDim.x) + blockIdx.x];
    myWord[0] = 'H';
    myWord[1] = 'e';
    myWord[2] = 'l';
    myWord[3] = 'l';
    myWord[4] = 'o';
}

Почему это не работает?

__global__ void setVal(char **word)
{

    char *myWord = word[(blockIdx.y * gridDim.x) + blockIdx.x];
    myWord = "Hello\0";

}

Ответы [ 2 ]

4 голосов
/ 04 июля 2011

Вы должны начать уделять гораздо больше внимания выводу компилятора.Ваш второй код ядра:

__global__ void setVal(char **word)
{
    char *myWord = word[(blockIdx.y * gridDim.x) + blockIdx.x];
    myWord = "Hello\0";
}

компилируется в нулевое ядро, в котором ничего нет:

$ nvcc -arch=sm_20 -c nullkernel.cu 
nullkernel.cu(3): warning: variable "myWord" was set but never used

nullkernel.cu(3): warning: variable "myWord" was set but never used

Причина в том, что то, что вы считаете назначением копирования строк, на самом деле простоназначение указателя, и в этом случае компилятор достаточно умен, чтобы знать, что myWord не записывается в память, поэтому он просто удаляет весь код и предупреждает вас, что myWord не используется.

Если бы язадайте риторический вопрос и переписайте код следующим образом:

__global__ void setVal(char **word)
{

    char *myWord = word[(blockIdx.y * gridDim.x) + blockIdx.x];
    const char[] mymsg = "Hello\0";
    myWord = mymsg;
}

было бы более очевидно как в том, почему код не компилируется, так и в том, почему он никогда не мог "неявно" выполнить присвоение строки, даже если онскомпилировал?

4 голосов
/ 04 июля 2011

Во второй версии, myWord = "Hello\0";, "Hello\0" не сохраняется в пространстве, заданном параметром **word. Строка хранится, вероятно, в разделе .rodata исполняемого файла. Присвоение просто обновляет указатель myWord - оно НЕ выполняет массовое копирование данных. (Хотя, как указывает talonmies , компилятор может выяснить, что обновление указателя не требуется вообще, и оптимизирует всю функцию. Опрятно.)

В общем, C не предоставляет никаких простых механизмов массового копирования данных, встроенных в язык - дизайнеры думали, что дорогие вещи должны выглядеть дорогими. Таким образом, в то время как PL / I делает присваивание 0 каждому элементу многомерного массива очень простой операцией: A = 0;, C заставляет вложенные циклы for() с операциями memset() в самом внутреннем цикле, чтобы вернуть домой Идея, что это дорого.

(Копирование struct элементов в параметр функции является единственным исключением из правила массового копирования.)

...