Приведение float * к char * во время циклического перемещения по двумерному массиву в линейной памяти на устройстве - PullRequest
4 голосов
/ 07 января 2012

На странице 21 руководства по программированию CUDA 4.0 приведен пример (приведенный ниже), иллюстрирующий циклическое элементы двумерного массива с плавающей точкой в ​​памяти устройства. Размеры 2D: ширина * высота

// Host code
int width = 64, height = 64;
float* devPtr;
size_t pitch;
cudaMallocPitch(&devPtr, &pitch,
width * sizeof(float), height);
MyKernel<<<100, 512>>>(devPtr, pitch, width, height);


// Device code
__global__ void MyKernel(float* devPtr, size_t pitch, int width, int height)
{
   for (int r = 0; r < height; ++r) 
    {
       float* row = (float*)((char*)devPtr + r * pitch);
          for (int c = 0; c < width; ++c) 
              {
              float element = row[c];
              }
     }
}

Почему указатель памяти устройства devPtr приведен к символьному указателю char * в функции ядра global ? Может кто-нибудь объяснить эту строку, пожалуйста. Это выглядит немного странно.

Ответы [ 3 ]

6 голосов
/ 07 января 2012

Это связано с тем, как арифметика указателя работает в C. Когда вы добавляете целое число x к указателю p, оно не всегда добавляет x байтов.Он добавляет x раз sizeof([type that p points to]).

float* row = (float*)((char*)devPtr + r * pitch);

. При приведении devPtr к char* применяется смещение (r * pitch*) с шагом в 1 байт.(потому что char это один байт).Если бы приведение не было там, смещение, примененное к devPtr, было бы r * pitch умножено на 4 байт, так как float - это четыре байта.

Например, если мы имеем:

float* devPtr = 1000;
int r = 4;

Теперь давайте не будем использовать приведение:

float* result1 = (devPtr + r);
// result1 = devPtr + (r * sizeof(float)) = 1016;

Теперь, если мы включим приведение:

float* result2 = (float*)((char*)devPtr + r);
// result2 = devPtr + (r * sizeof(char)) = 1004;
1 голос
/ 07 января 2012

Приведение предназначено только для того, чтобы арифметика указателя работала правильно;

(float*)((char*)devPtr + r * pitch);

перемещает r * питч байтов вперед, в то время как

(float*)(devPtr + r * pitch);

будет перемещать r * поле плавает вперед (т.е. 4раз больше байтов)

0 голосов
/ 10 января 2012

*(devPtr + 1) сместит указатель на 4 байта (sizeof(float)), прежде чем * прекратит его разыменование.*((char)devPtr + 1) сместит указатель на 1 байт (sizeof(char)), прежде чем * разыменует его ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...