Ошибка cudaMemset для переменной __device__ - PullRequest
1 голос
/ 03 апреля 2012

У меня проблемы с использованием cudaMemset в переменной устройства. Можно ли использовать ссылку на переменную устройства для cudaMemset, или это просто вопрос отсутствия флагов компилятора или библиотек ... Я использую cuda 4.1 и

Версия NVRM: Модуль ядра NVIDIA UNIX x86_64 285.05.33 Чт 19 января 14:07:02 PST 2012

Это мой пример кода:

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

// device variable and kernel
__device__ float d_test;

int main() {

  if (cudaMemset(&d_test,0,sizeof(float)) !=cudaSuccess)
        printf("Error!\n");
}

который выводит:

Error!

Ответы [ 2 ]

5 голосов
/ 03 апреля 2012

Ваша проблема в том, что d_test (как это показано в таблице символов хоста) не является допустимым адресом устройства, и среда выполнения не может получить к нему прямой доступ. Решение состоит в том, чтобы использовать функцию API cudaGetSymbolAddress для считывания адреса символа устройства из контекста во время выполнения. Вот несколько расширенная версия демонстрационного кейса, которая должна работать правильно:

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

// device variable and kernel
__device__ float d_test;

inline void gpuAssert(cudaError_t code, char * file, int line, bool Abort=true)
{
    if (code != cudaSuccess) {
        fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code),file,line);
        if (Abort) exit(code);
    }       
}

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }

int main()
{

    float * _d_test;

    gpuErrchk( cudaFree(0) );
    gpuErrchk( cudaGetSymbolAddress((void **)&_d_test, "d_test") );
    gpuErrchk( cudaMemset(_d_test,0,sizeof(float)) );

    gpuErrchk( cudaThreadExit() );

    return 0;
}

Здесь мы читаем адрес символа устройства d_test из контекста в указатель хоста _d_test. Затем его можно передать API-функциям на стороне хоста, таким как cudaMemset, cudaMemcpy и т. Д.


Отредактируйте, чтобы отметить, что форма cudaGetSymbolAddress, показанная в этом ответе, устарела и удалена из API времени выполнения CUDA. Для современной CUDA вызов будет:

gpuErrchk( cudaGetSymbolAddress((void **)&_d_test, d_test) );
0 голосов
/ 24 октября 2012

Полагаю, вы также можете использовать cudaMemcpyFromSymbol: Функция, такая как следующее ядро, может изменить значение переменной, объявленной в глобальной памяти (вне основной функции)

__global__ void kernel1() { d_test = 1.0; }

Внутри вашего основного вы можете получить значение, используя cudaMemcpyFromSymbol

cudaMemcpyFromSymbol(&h_test,"d_test",sizeof(float),0,cudaMemcpyDeviceToHost);

Конечно, существует также cudaMemcpyToSymbol для изменения значения глобальной переменной.

Идея пришла отсюда: Возникли проблемы с назначением переменной устройства в CUDA

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...