Временные массивы устройств CUDA

0

Играя с этим великим экспериментом CUDA в течение нескольких месяцев, я обнаружил, что больше экспериментирую и пытаюсь отвлечься от примеров учебников.

Мой вопрос таков: если я хочу просто использовать массивы на графическом процессоре для чего-то вроде временного хранилища, не копируя их обратно на хост для отображения/вывода, могу ли я просто создать массив устройств с __device__ double array[numpoints]; Тогда для чего-нибудь, что я хочу взять с GPU, мне нужно сделать весь cudaMalloc, cudaMemcpy spiel, правильно? Кроме того, существует ли какая-либо разница между тем или иным способом? Я думал, что они оба создают массивы в глобальной памяти.

Теги:
cuda

2 ответа

1

Вы можете создавать, заполнять и использовать массивы памяти 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;
}
1

См. Это описание о квалификаторе __device__. Поэтому, если вы объявляете его __device__ вы не можете получить к нему доступ в хосте через cudaMemcpy но есть другие, упомянутые в ссылке.

Вместо этого вы можете объявить глобальный указатель (т. __device__ Без __device__) в коде хоста и выделить с помощью cudaMalloc. Таким образом, вы можете использовать то же самое, чтобы скопировать результат обратно на хост с помощью cudaMemcpy.

  • 4
    cudaMemcpy можно использовать для копирования в статически объявленную память __device__ . Вот для чего cudaGetSymbolAddress и cudaGetSymbolSize - вы можете получить подробную информацию о статических символах во время выполнения, а затем использовать их, как и любой другой адрес хоста.
  • 0
    @talonmies: Хорошо это знать. Только что попробовал, и это работает, спасибо. Если бы вы ответили так же, я бы высказался по этому поводу (похоже, это то, что ищет автор вопроса).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню