Играя с этим великим экспериментом CUDA в течение нескольких месяцев, я обнаружил, что больше экспериментирую и пытаюсь отвлечься от примеров учебников.
Мой вопрос таков: если я хочу просто использовать массивы на графическом процессоре для чего-то вроде временного хранилища, не копируя их обратно на хост для отображения/вывода, могу ли я просто создать массив устройств с __device__ double array[numpoints];
Тогда для чего-нибудь, что я хочу взять с GPU, мне нужно сделать весь cudaMalloc, cudaMemcpy spiel, правильно? Кроме того, существует ли какая-либо разница между тем или иным способом? Я думал, что они оба создают массивы в глобальной памяти.
Вы можете создавать, заполнять и использовать массивы памяти globl без необходимости использования cudaMemcpy
для копирования данных с хоста для инициализации, если это то, что вы просите. В следующем простом примере я создаю массив глобальной памяти, который инициализируется непосредственно на устройстве, а затем я освобождаю его, когда он больше не нужен.
#include<stdio.h>
__global__ void init_temp_data(float* temp_data) {
temp_data[threadIdx.x] = 3.f;
}
__global__ void copy_global_data(float* temp_data, float* d_data) {
d_data[threadIdx.x] = temp_data[threadIdx.x];
}
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
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);
}
}
int main() {
float* data = (float*)malloc(16*sizeof(float));
float* d_data; gpuErrchk(cudaMalloc((void**)&d_data,16*sizeof(float)));
float* temp_data; gpuErrchk(cudaMalloc((void**)&temp_data,16*sizeof(float)));
init_temp_data<<<1,16>>>(temp_data);
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
copy_global_data<<<1,16>>>(temp_data,d_data);
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
gpuErrchk(cudaFree(temp_data));
gpuErrchk(cudaMemcpy(data,d_data,16*sizeof(float),cudaMemcpyDeviceToHost));
for (int i=0; i<16; i++) printf("Element number %i is equal to %f\n",i,data[i]);
getchar();
return 0;
}
См. Это описание о квалификаторе __device__
. Поэтому, если вы объявляете его __device__
вы не можете получить к нему доступ в хосте через cudaMemcpy
но есть другие, упомянутые в ссылке.
Вместо этого вы можете объявить глобальный указатель (т. __device__
Без __device__
) в коде хоста и выделить с помощью cudaMalloc
. Таким образом, вы можете использовать то же самое, чтобы скопировать результат обратно на хост с помощью cudaMemcpy
.
__device__
. Вот для чегоcudaGetSymbolAddress
иcudaGetSymbolSize
- вы можете получить подробную информацию о статических символах во время выполнения, а затем использовать их, как и любой другой адрес хоста.