Проблема с назначением переменной устройства в CUDA
У меня возникли проблемы с попыткой присвоить значение переменной устройства и затем скопировать ее в переменную хоста.
Я начинаю с d_test и h_test = 0.0. У меня есть простое ядро для установки переменной устройства d_test на 1.0. Затем я копирую его в переменную хоста h_test и печатаю. Проблема в том, что при печати я получаю h_test = 0.0. Что я делаю не так? Здесь код:
// -*- mode: C -*-
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
// device variable and kernel
__device__ float d_test;
__global__ void kernel1(float d_test) { d_test = 1.0; }
int main() {
// initialise variables
float h_test = 0.0;
cudaMemset(&d_test,0,sizeof(float));
// invoke kernel
kernel1 <<<1,1>>> (d_test);
// Copy device variable to host and print
cudaMemcpy(&h_test,&d_test,sizeof(float),cudaMemcpyDeviceToHost);
printf("%f\n",h_test);
}
Ответы
Ответ 1
В вашем коде есть несколько проблем.
-
Как правильно отмечает pezcode, параметр kernel1
d_test
затеняет вашу глобальную переменную, поэтому, когда она назначает d_test
, она фактически меняет значение своего параметра, а не глобальную переменную, как вы собираетесь, kernel1
не нужно принимать аргумент в этом примере.
-
Вместо cudaMemcpy
используйте cudaMemcpyFromSymbol
при копировании из глобальной переменной __device__
.
Здесь полное решение:
// -*- mode: C -*-
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>
// device variable and kernel
__device__ float d_test;
__global__ void kernel1() { d_test = 1.0; }
int main() {
// initialise variables
float h_test = 0.0;
cudaMemset(&d_test,0,sizeof(float));
// invoke kernel
kernel1 <<<1,1>>> ();
// Copy device variable to host and print
cudaMemcpyFromSymbol(&h_test, "d_test", sizeof(float), 0, cudaMemcpyDeviceToHost);
printf("%f\n",h_test);
}
И вывод:
$ nvcc test.cu -run
1.000000
Ответ 2
cudaMemcpyFromSymbol работал у меня после долгой борьбы с cudaMemcpy и получения неправильных значений. Мне пришлось удалить кавычки вокруг "d_test" и получить недопустимую ошибку аргумента с помощью cudaMemset, поэтому просто использовал cudaMalloc, который ранее был в коде.
Ответ 3
Я предполагаю, что kernel1 изменяет свой параметр d_test, поскольку он скрывает глобальную переменную device.
Переименуйте один из них или если это работает с CUDA, явным образом использую глобальную область видимости, задав:: d_test.
Ответ 4
этот код работает для меня отлично. ключ есть.
вторая переменная должна быть такой, как \n
cudaMemcpyFromSymbol (& h_test, d_test, sizeof (float), 0, cudaMemcpyDeviceToHost);
а затем скомпилируйте свой код с помощью
nvcc -Xcompiler -arch = sm_30 sample.cu -o sample.exe