Cuda повторное использование общей переменной имени памяти
У меня есть два ядра cuda, которые запускаются, одно за другим:
__global__
void calculate_histo(const float* const d_logLuminance,
unsigned int* d_histogram,
float min_logLum,
float lumRange,
int numBins,
int num_elements){
extern __shared__ float sdata[];
int tid = threadIdx.x;
int bid = blockIdx.x;
int gid = tid * blockDim.x + bid;
// load input into __shared__ memory
if(gid < num_elements)
{
sdata[tid] = d_logLuminance[gid];
__syncthreads();
//compute bin value of input
int bin = static_cast <int> (floor((d_logLuminance[gid]-min_logLum)/ lumRange * numBins));
//increment histogram at bin value
atomicAdd(&(d_histogram[bin]), 1);
}
}
__global__
void blelloch_scan(unsigned int* const d_cdf, unsigned int* d_histogram, int numBins) {
extern __shared__ unsigned int sdata[];// allocated on invocation
int thid = threadIdx.x;
//printf("%i \n", thid);
//printf("%i \n", d_histogram[thid]);
int offset = 1;
sdata[2*thid] = d_histogram[2*thid]; // load input into shared memory
sdata[2*thid+1] = d_histogram[2*thid+1];
// build sum in place up the tree
for (int d = numBins>>1; d > 0; d >>= 1) {
__syncthreads();
if (thid < d) {
int ai = offset*(2*thid+1)-1;
int bi = offset*(2*thid+2)-1;
sdata[bi] += sdata[ai];
}
offset *= 2;
}
if (thid == 0) { sdata[numBins - 1] = 0; } // clear the last element
// traverse down tree & build scan
for (int d = 1; d < numBins; d *= 2) {
offset >>= 1;
__syncthreads();
if (thid < d) {
int ai = offset*(2*thid+1)-1;
int bi = offset*(2*thid+2)-1;
float t = sdata[ai];
sdata[ai] = sdata[bi];
sdata[bi] += t;
}
__syncthreads();
d_cdf[2*thid] = sdata[2*thid]; // write results to device memory
d_cdf[2*thid+1] = sdata[2*thid+1];
}
}
Они оба используют общую память. Второй имеет неподписанный массив int в качестве разделяемой памяти. Первый имеет массив с плавающей точкой. Я подумал, что смогу использовать одно и то же имя переменной sdata для обоих массивов, так как разделяемая память очищается после каждого запуска ядра, но я получаю сообщение об ошибке:
declaration is incompatible with previous 'sdata'
Если я использую разные имена переменных для каждого ядра, это, похоже, решит проблему. Кто-нибудь знает, почему я не могу использовать одно и то же имя переменной?
1 ответ
CUDA просто следует правилу стандартного языка Си. Цитирую книгу Кернигана и Ричи "Язык программирования С":
Внешняя переменная должна быть определена ровно один раз за пределами любой функции; это отводит хранилище для него. Переменная также должна быть объявлена в каждой функции, которая хочет получить к ней доступ; здесь указывается тип переменной. [...] Определение относится к месту, где переменная создается или назначается хранилище; Декларация относится к местам, где указана природа переменной, но хранилище не выделено.
Где-то в вашей программе у вас должно быть что-то вроде
extern __shared__ unsigned int sdata[];
В этом месте вы создаете указатель с именем sdata
, для unsigned int
, Внутри __global__
функции, которые вы объявляете тип sdata
, таким образом __global__
функция может знать об этом. в
kernel<<<blocks,threads,numbytes_for_shared>>>(...);
запустить, вы выделяете пространство массива, на который указывает sdata
,