Я унаследовал некоторый код CUDA, над которым мне нужно поработать, но некоторая индексация, выполненная в нем, сбивает меня с толку.
Простым примером была бы нормализация данных. Скажем, у нас есть общий массив A[2*N]
, который представляет собой матрицу формы 2xN, развернутую в массив. Тогда у нас есть средства нормализации и стандартное отклонение: norm_means[2]
и norm_stds[2]
. Цель состоит в том, чтобы нормализовать данные в A параллельно. Минимальный пример:
__global__ void normalise(float *data, float *norm, float *std) {
int tdy = threadIdx.y;
for (int i=tdy; i<D; i+=blockDim.y)
data[i] = data[i] * norm[i] + std[i];
}
int main(int argc, char **argv) {
// generate data
int N=100;
int D=2;
MatrixXd A = MatrixXd::Random(N*D,1);
MatrixXd norm_means = MatrixXd::Random(D,1);
MatrixXd norm_stds = MatrixXd::Random(D,1);
// transfer data to device
float* A_d;
float* norm_means_d;
float* nrom_stds_d;
cudaMalloc((void **)&A_d, N * D * sizeof(float));
cudaMalloc((void **)&norm_means_d, D * sizeof(float));
cudaMalloc((void **)&norm_stds_d, D * sizeof(float));
cudaMemcpy(A_d, A.data(), D * N * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(norm_means_d, norm_means.data(), D * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(norm_stds_d, norm_stds.data(), D * sizeof(float), cudaMemcpyHostToDevice);
// Setup execution
const int BLOCKSIZE_X = 8;
const int BLOCKSIZE_Y = 16;
const int GRIDSIZE_X = (N-1)/BLOCKSIZE_X + 1;
dim3 dimBlock(BLOCKSIZE_X, BLOCKSIZE_Y, 1);
dim3 dimGrid(GRIDSIZE_X, 1, 1);
normalise<<dimGrid, dimBlock, 0>>>(A_d, norm_means_d, norm_stds_d);
}
Обратите внимание, что я использую Eigen для генерации матрицы. Для краткости я пропустил включения:
Этот код, приведенный выше, через некоторые маги c работает и достигает желаемых результатов. Однако функция ядра CUDA не имеет для меня никакого смысла, потому что for l oop должен останавливаться после одного выполнения как i>D
после первой итерации ... но это не так?
Если я изменю ядро, которое имеет для меня больше смысла, например.
__global__ void normalise(float *data, float *norm, float *std) {
int tdy = threadIdx.y;
for (int i=0; i<D; i++)
data[tdy + i*blockDim.y] = data[tdy + i*blockDim.y] * norm[i] + std[i];
}
, программа перестает работать и просто выводит данные gibberi sh.
Может кто-нибудь объяснить, почему у меня такое поведение?
PS. Я очень новичок в CUDA