2013-03-28 1 views
1

Причина, почему я спрашиваю это потому, что есть какая-то странная ошибка в моем коде, и я подозреваю, что это может быть какой-то алиасинг проблема:Поддерживает ли CUDA указатель-сглаживание?

__shared__ float x[32]; 
__shared__ unsigned int xsum[32]; 

int idx=threadIdx.x; 
unsigned char * xchar=(unsigned char *)x; 
//...do something 
if (threadIdx.x<32) 
{ 
    xchar[4*idx]&=somestring[0]; 
    xchar[4*idx+1]&=somestring[1]; 
    xchar[4*idx+2]&=somestring[2]; 
    xchar[4*idx+3]&=somestring[3]; 

    xsum[idx]+=*((unsigned int *)(x+idx));//<-Looks like the compiler sometimes fail to recongize this as the aliasing of xchar; 
}; 
+0

Почему вы не ставите '__shared__' перед' unsigned char * xchar'? То же самое для '(unsigned int *) x'. – thejh

+0

@thejh Мне нужно сделать это здесь? – user0002128

+0

Не уверен, но я так думаю. Вы можете попробовать, может ли это сделать ваш код ... – thejh

ответ

1

Я думаю, что у вас есть условие гонки здесь. Но я не знаю, что такое somestring. Если одно и то же для всех потоков, которые вы можете сделать так:

__shared__ float x[32]; 

unsigned char * xchar=(unsigned char *)x; 

//...do something 

if(threadIdx.x<4) { 
    xchar[threadIdx.x]&=somestring[threadIdx.x]; 
} 

__syncthreads(); 

unsigned int xsum+=*((unsigned int *)x); 

Это означает, что каждая нить разделяет тот же массив и, следовательно, xsum тот же между всеми потоками. Если вы хотите, чтобы каждый поток имел свой собственный массив, вы должны выделить массив из 32*number_of_threads_in_block и использовать смещение.

PS: код выше работает только в блоке 1D. В 2D или 3D вы должны вычислить свой собственный threadID и убедиться, что только 4 потока выполняют код.

+0

Мое извинение, код примера вводит в заблуждение, я просто пытался сохранить несколько строк кода в этом примере, в моем исходном коде нет условия гонки. – user0002128

+0

@ user0002128 ОК, поэтому я предполагаю, что вы выделяете память во время выполнения, иначе она будет работать только для блока из 32 потоков. – Seltymar

2

Компилятор должен выполнять только псевдонимы между совместимыми типами. Поскольку char и float несовместимы, компилятор может предположить, что указатели никогда не являются псевдонимами.

Если вы хотите выполнять побитовые операции над float, сначала конвертируйте (через __float_as_int()) в unsigned integer, затем оперируйте его и, наконец, преобразуйте обратно в float (используя __int_as_float()).

+0

Что-то я не понимаю. В руководстве по программированию стр.85 они объявляют 'array0' с другим типом, указывающим на память' array'. Здесь есть псевдонимы, верно? Если я использую 'array' после модификации' array0', я должен получить измененное значение? – Seltymar

+1

Это не определено. В [example] (http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#shared) подразумевается, что 'array' никогда не открывается. Он служит только для выделения памяти для поддержки 'array0',' array1' и 'array2'. – tera