CUDA: поиск индекса массива в двумерном массиве, выделенном с помощью cudaMallocPitch

Я работал над реализацией игры с использованием cuda. Я хочу найти индекс массива каждого элемента, чтобы я мог вычислить соседей для этого элемента и чтобы я мог записать новое значение в этот массив. Все, что я нашел по этому поводу, работает с указателями на строки, и я просто не могу понять, как это в точности соответствует индексам. Чтобы дать лучшее представление о том, что я имею в виду, я должен следующий код (некоторые фрагменты):

#define THREADSPERBLOCK 1024
lifeState *d_gameStateInitial;
size_t d_gameStateInitial_pitch;
int sizeX = 100;
int sizeY = 100;

int numBlocks = ((sizeX * sizeY) % THREADSPERBLOCK) + 1;
int numThreadsPerBlock;

if(numBlocks == 1)
{
numThreadsPerBlock = sizeX * sizeY;
}
else
{
numThreadsPerBlock = THREADSPERBLOCK;
}

cudaMallocPitch((void **)&d_gameStateInitial, &d_gameStateInitial_pitch, sizeX * sizeof(lifeState), sizeY);

doTheGame<<<numBlocks, numThreadsPerBlock>>>(d_gameStateInitial, d_gameStateInitial_pitch, d_gameStateNew, d_gameStateNew_pitch, sizeX, sizeY);

«Lifestate *» — это просто структура, содержащая перечисление dead / alive. Оба массива, начальный и новый, имеют одинаковый malloc. В ядре doTheGame теперь я хочу узнать, как рассчитать индекс, я думал о чем-то вроде этого, но думаю, что это неправильно:

__global__ void doTheGame(lifeState *initialArray, size_t initialArrayPitch,
lifeState *newArray, size_t newArrayPitch,
int sizeX, int sizeY)
{
int initialArrayThreadIndex = (blockIdx.x * initialArrayPitch) + threadIdx.x;
int newArrayThreadIndex = (blockIdx.x * initialArrayPitch) + threadIdx.x;
}

Все, что я нашел до сих пор, в основном совпадает с примером cudaMallocPitch:

  T* pElement = (T*)((char*)BaseAddress + Row * pitch) + Column;

Но я просто не могу понять, как это преобразуется в блоки, потоки и x и y точно.

Заранее спасибо.

0

Решение

Предположим, у меня есть double data[] массив, как это:

A  B  C  D  x  x  x  x
E  F  G  H  x  x  x  x

затем data[0] = A, data[1] = B и т.п.

Это может быть результатом выделения массива 2×4 с шагом в 64 байта (таким образом, 4 дополнительных x записи в каждом ряду). Давайте предположим, что каждый элемент в массиве выше double количество.

Теперь предположим, что у меня есть ядро, и я запускаю массив потоков 2х4, по одному на каждый допустимый элемент ( x элементы недействительны — они являются дополнительными выделениями для удовлетворения требования основного тона, которое произвольно выбрано для этого примера, чтобы быть 64 байтами).

В этом ядре я мог бы создать индексы x и y следующим образом:

int idx = threadIdx.x +blockDim.x * blockIdx.x;
int idy = threadIdx.y +blockDim.y * blockIdx.y;

Каждый поток может затем получить доступ к своему соответствующему элементу следующим образом.

Так как pitch количество, возвращаемое cudaMallocPitch в байтах, нам нужно сначала вычислить смещение строки, используя char арифметика указателей:

double *rowptr = (double *)((char *)data + idy*pitch);

Затем мы можем получить доступ к элементу в этой строке следующим образом:

rowptr[idx] = 0.0;

Если я хочу, чтобы поток обращался к элементу, отличному от того, который соответствует его индексам потока, вычисления аналогичны.

Например установить элемент G (т.е. элемент (1,2)) к нулю в приведенном выше data массив, я мог бы сделать:

double *rowptr = (double *)((char *)data + 1*pitch);
rowptr[2] = 0.0;
3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]