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

0

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

#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 *" - это просто структура, содержащая переиздание "мертвое/живое". Оба массива, исходные и новые, являются malloc'd точно так же. В ядре 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;

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

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

  • 0
    Я не вижу здесь вопроса. Что именно вы хотите знать?
Теги:
arrays
cuda
conways-game-of-life

1 ответ

3
Лучший ответ

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

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

Тогда data[0] = A, data[1] = B и т.д.

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

Теперь предположим, что у меня есть ядро, и я запускаю массив из 2x4 потоков, по одному на допустимый элемент (элементы 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;
  • 0
    Я задал тот же вопрос, прежде чем найти этот, но я не могу последовать вашему примеру. Похоже, вы не проверяете, находится ли rowptr в массиве, что сработало бы, только если вы тщательно манипулировали количеством потоков и блоков. Кроме того, может показаться, что вы проходите сквозь слепые элементы. Можете ли вы опубликовать более полный пример?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню