Одна возможность состоит в том, чтобы непосредственно инициализировать __device__
массив на GPU, если он имеет постоянный размер, добавив следующую декларацию в области видимости файла (то есть, вне какой-либо функции):
__device__ int dev_array[SIZE] = {1, 1};
Остальные элементы будут инициализирован с нули (вы можете проверить сборку PTX, чтобы убедиться в этом).
тогда, он может быть использован в ядре, как:
__global__ void kernel(void)
{
int tid = ...;
int elem = dev_array[tid];
...
}
В случае переменного размера, вы можете комбинировать cudaMalloc()
с cudaMemset()
:
int array_size = ...;
int *dev_array;
cudaMalloc((void **) &dev_array, array_size * sizeof(int));
cudaMemset(dev_array, 0, array_size * sizeof(int));
затем установите первые два элемента, как те:
int helper_array[2] = {1, 1};
cudaMemcpy(dev_array, helper_array, 2 * sizeof(int), cudaMemcpyHostToDevice);
Начиная с вычислительной способности 2.0 вы можете также выделить весь массив непосредственно внутри ядра с помощью функции malloc()
устройства:
__global__ void kernel(int array_size)
{
int *dev_array;
int tid = ...;
if (tid == 0) {
dev_array = (int *) malloc(array_size * sizeof(int));
if (dev_array == NULL) {
...
}
memset(dev_array, 0, array_size * sizeof(int));
dev_array[0] = dev_array[1] = 1;
}
__syncthreads();
...
}
Обратите внимание, что нити из разных блоков не знают о синхронизации барьера.
Из CUDA C Programming Guide:
CUDA в ядре malloc()
функция выделяет, по меньшей мере size
байт из кучи устройства и возвращает указатель на выделенную память или NULL
, если существует недостаточно памяти для выполнения запроса , Возвращаемый указатель должен быть выровнен с 16-байтной границей.
К сожалению, функция calloc()
не реализована, поэтому вам все равно нужно ее сменить.Выделенная память имеет срок службы CUDA контекста, но вы можете явно назвать free()
от этого или последующего ядра в любой момент:
память выделяется с помощью данной CUDA нити через malloc()
остается выделенным для жизни контекста CUDA, или до тех пор, пока не будет , явно выпущенный по вызову free()
. Он может использоваться любыми другими потоками CUDA даже после запуска ядра.
Со всем, что сказал, я не возражал бы, что много о дополнительном cudaMemcpy()
, так как это только два элемента, чтобы скопировать и было бы вероятно занимает менее 0,01% от общего времени выполнения (это легко профиль). Выберите любой способ, который сделает код четким. В противном случае это premature optimization.
Вы считали, что 'calloc' (который инициализирует нуль) вместо' malloc', а затем только первые 2 элемента в 1 (как и вы)? –
@Blue Moon, thx для идеи, но операция calloc недоступна для программ CUDA. – Bakus123
Лучше использовать 'cudaMemset' вместо цикла. – haccks