Вектор доступа указателей к другим векторам на графическом процессоре

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

for(int i =0;i<N;i++){

dgemm(A[i], B[i],C[i], Size[i][0], Size[i][1], Size[i][2], Size[i][3], 'N','T');

}

где A [i] будет двухмерной матрицей некоторого размера.

Я хотел бы иметь возможность делать это на GPU с использованием CULA (я не просто делаю умножения, поэтому мне нужны операции Linear ALgebra в CULA), например, так:

 for(int i =0;i<N;i++){
status = culaDeviceDgemm('T', 'N', Size[i][0], Size[i][0], Size[i][0], alpha, GlobalMat_d[i], Size[i][0], NG_d[i], Size[i][0], beta, GG_d[i], Size[i][0]);
}

но я хотел бы заблаговременно сохранять свои B на GPU в начале программы, так как они не меняются, поэтому мне нужно иметь вектор, который содержит указатели на набор векторов, составляющих мои B.

В настоящее время у меня есть следующий код, который компилируется:

double **GlobalFVecs_d;
double **GlobalFPVecs_d;

extern "C" void copyFNFVecs_(double **FNFVecs, int numpulsars, int numcoeff){cudaError_t err;
GlobalFPVecs_d = (double **)malloc(numpulsars * sizeof(double*));
err = cudaMalloc( (void ***)&GlobalFVecs_d, numpulsars*sizeof(double*) );
checkCudaError(err);

for(int i =0; i < numpulsars;i++){
err = cudaMalloc( (void **) &(GlobalFPVecs_d[i]), numcoeff*numcoeff*sizeof(double) );
checkCudaError(err);
err = cudaMemcpy( GlobalFPVecs_d[i], FNFVecs[i], sizeof(double)*numcoeff*numcoeff, cudaMemcpyHostToDevice );
checkCudaError(err);
}

err = cudaMemcpy( GlobalFVecs_d, GlobalFPVecs_d, sizeof(double*)*numpulsars, cudaMemcpyHostToDevice );
checkCudaError(err);

}

но если я сейчас попробую получить к нему доступ:

 dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
dim3 dimGrid;//((G + dimBlock.x - 1) / dimBlock.x,(N + dimBlock.y - 1) / dimBlock.y);
dimGrid.x=(numcoeff + dimBlock.x - 1)/dimBlock.x;
dimGrid.y = (numcoeff + dimBlock.y - 1)/dimBlock.y;

for(int i =0; i < numpulsars; i++){
CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFVecs_d[i], numpulsars, numcoeff, i);
}

здесь обнаруживаются ошибки, разве это не как получить данные?

Функция Kernal, которую я вызываю, просто:

__global__ void CopyPPFNF(double *FNF_d, double *PPFNF_d, int numpulsars, int numcoeff, int thispulsar) {

// Each thread computes one element of C
// by accumulating results into Cvalueint row = blockIdx.y * blockDim.y + threadIdx.y;
int col = blockIdx.x * blockDim.x + threadIdx.x;

int subrow=row-thispulsar*numcoeff;
int subcol=row-thispulsar*numcoeff;

__syncthreads();
if(row >= (thispulsar+1)*numcoeff || col >= (thispulsar+1)*numcoeff) return;
if(row < thispulsar*numcoeff || col < thispulsar*numcoeff) return;FNF_d[row * numpulsars*numcoeff + col] += PPFNF_d[subrow*numcoeff+subcol];

}

Что я не правильно делаю? Обратите внимание, что в конце концов я также хотел бы сделать в качестве первого примера вызов функций cula для каждого GlobalFVecs_d [i], но сейчас даже это не работает.

Как вы думаете, это лучший способ сделать это? Если бы можно было просто передать функции CULA срез большого непрерывного вектора, я мог бы сделать это, но я не знаю, поддерживает ли это это.

ура
Линдли

0

Решение

изменить это:

CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFVecs_d[i], numpulsars, numcoeff, i);

к этому:

CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFPVecs_d[i], numpulsars, numcoeff, i);

и я верю, что это сработает.

Ваша методология работы с указателями в основном правильная. Тем не менее, когда вы кладете GlobalFVecs_d[i] в списке параметров вы заставляете код установки ядра (работающий на хосте) принять GlobalFVecs_d (указатель устройства, созданный с cudaMalloc), добавьте соответственно масштабированный i к значению указателя, а затем разыменовывать результирующий указатель получить значение для передачи в качестве параметра ядру. Но мы не положено разыменовать указатели устройства в коде хоста.

Однако, поскольку ваша методология была в основном правильной, у вас есть удобный параллельный массив из одни и те же указатели который находится на хосте. Этот массив (GlobalFPVecs_d) — это то, к чему нам разрешено обращаться в коде хоста, чтобы получить результирующий указатель устройства и передать его ядру.

Это интересная ошибка, потому что обычно ядра не выдают ошибку (хотя они могут выдать ошибку), поэтому ошибка сегмента в строке вызова ядра является необычной. Но в этом случае ошибка seg происходит в коде установки ядра, а не в самом ядре.

0

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

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