На CUDA __constant__ памяти и на нескольких графических процессорах?

0

В модели программирования с общей памятью любые глобальные переменные видны для каждого потока.

В CUDA постоянная память объявляется аналогично глобальным переменным в системах с разделяемой памятью, что меня немного беспокоит:

Учитывая следующий код:

__constant__ int array[1024];

void hostFunction(int DeviceID, cudaStream_t streamIdx)
{
    cudaSetDevice(DeviceID);
    someKernel<<<100,1024,0, streamIdx>>>(...);
    //The function someKernel will use data stored in array[] on current device;
};

Затем: Является ли содержимое array[] локальным для каждого контекста/устройств cuda, так что мы можем безопасно обновлять каждый "частный" array[] не беспокоясь об изменении значений array[] выделенных на других устройствах cuda?

BTW: Я искал сайт, есть некоторые связанные вопросы, однако я не могу найти никакого ясного ответа от любого из них.

Теги:
arrays
cuda

1 ответ

4
Лучший ответ

Затем: Является ли содержимое массива [] локальным для каждого контекста/устройств cuda, так что мы можем безопасно обновлять каждый "частный" массив устройств, не беспокоясь об изменении значений массива [], выделенных на других устройствах cuda?

Да, единственная строка кода

__constant__ int array[1024];

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

Затем вы можете индивидуально загружать память __constant__ на каждое устройство, используя, например:

cudaSetDevice(0);
cudaMemcpyToSymbol(array, my_device_0_constant_data, 1024*sizeof(int));

и повторите описанное выше для каждого устройства, которое вы хотите использовать.

Аналогичные утверждения могут быть сделаны относительно переменных __device__.

Вот полный пример:

$ cat t223.cu
#include <stdio.h>

#define cudaCheckErrors(msg) \
    do { \
        cudaError_t __err = cudaGetLastError(); \
        if (__err != cudaSuccess) { \
            fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
                msg, cudaGetErrorString(__err), \
                __FILE__, __LINE__); \
            fprintf(stderr, "*** FAILED - ABORTING\n"); \
            exit(1); \
        } \
    } while (0)

__constant__ int my_const_data;

__device__ int my_dev_data;

__global__ void my_kernel(int my_dev){

  printf("device %d constant data is: %d\n", my_dev, my_const_data);
  printf("device %d __device__ data is: %d\n", my_dev, my_dev_data);
}

int main(){

  int num_dev = 0;
  cudaGetDeviceCount(&num_dev);
  cudaCheckErrors("get device count fail");
  if (num_dev == 0) {printf("no cuda devices found!\n"); return 1;}
  for (int i = 0; i < num_dev; i++){
    int cdata = i;
    int ddata = 10*i;
    cudaSetDevice(i);
    cudaMemcpyToSymbol(my_const_data, &cdata, sizeof(int));
    cudaMemcpyToSymbol(my_dev_data, &ddata, sizeof(int));
    cudaCheckErrors("memcpy to symbol fail");}
  for (int i = 0; i < num_dev; i++){
    cudaSetDevice(i);
    my_kernel<<<1,1>>>(i);
    cudaDeviceSynchronize();}
  cudaCheckErrors("kernel fail");
  return 0;
}

$ nvcc -arch=sm_20 -o t223 t223.cu
$ ./t223
device 0 constant data is: 0
device 0 __device__ data is: 0
device 1 constant data is: 1
device 1 __device__ data is: 10
device 2 constant data is: 2
device 2 __device__ data is: 20
device 3 constant data is: 3
device 3 __device__ data is: 30
$
  • 0
    Большое спасибо за этот подробный ответ.

Ещё вопросы

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