возникают проблемы, связанные с умножением матрицы с использованием cuda. Я должен сделать A * A * A * A и сохранить его в hB. С Cublas это нормально, но я не могу сделать это с CUDA. Размер может быть большим значением, например 2000. Это мой код:
__global__ void CudaMM(float *A, float *B, int N)
{
int row = blockIdx.y*blockDim.y + threadIdx.y;
int col = blockIdx.x*blockDim.x + threadIdx.x;
float sum = 0.f;
for (int n = 0; n < N; ++n)
sum += A[row*N+n]*A[n*N+col];
B[row*N+col] = sum;
}
void CudaMult(int dimension,float *hMatrice,float *hB,float *d_A,float *d_B){
int N,K;
K = 100;
N = K*BLOCK_SIZE;
dim3 threadBlock(BLOCK_SIZE,BLOCK_SIZE);
dim3 grid(K,K);
cudaMemcpy(d_A,hMatrice,dimension*dimension*sizeof(float),cudaMemcpyHostToDevice);
CudaMM<<<grid,threadBlock>>>(d_A,d_B,N);
cudaMemcpy(hB,d_B,dimension*dimension*sizeof(float),cudaMemcpyDeviceToHost);
}
void CublasFindConnect(int dimension,float* mat,float* B){
float *d_A,*d_B;
cudaMalloc(&d_A,dimension*dimension*sizeof(float));
cudaMalloc(&d_B,dimension*dimension*sizeof(float));
int w=0;
while(w<5){
CudaMult(dimension,mat,B,d_A,d_B);
// Copy Matrix computed B to previous M
for (m=0; m<dimension; m++) {
for (n=0; n<dimension; n++) {
mat[m*dimension+n]=B[m*dimension+n];
B[m*dimension+n]=0;
}
}
w++;
}
cudaFree(d_A);
cudaFree(d_B);
}
Я установил последний CUDA 6, который не требует cudaMemCpy, потому что память разделяется.
BLOCK_SIZE
? Идея не в том, чтобы рассказать мне, что BLOCK_SIZE
, но и показать полный код.cudaMallocManaged()
), которые вы не встречаете, но тем не менее ваш код не зависит от Unified Memory, поэтому он не имеет значения. Одна из проблем, которые я вижу в вашем коде, заключается в том, что ваша dimension
переменная произвольна (вы говорите, что она может быть до большого числа, такого как 2000), но ваш размер вычислений фиксирован в N=K*BLOCK_SIZE;
, Предположительно, если ваш BLOCK_SIZE имеет некоторое значение, например 16 или 32, он будет соответствовать вашему приблизительному максимальному dimension
размера ~ 2000.
Проблема возникает из-за того, что размер вашей сетки потенциально больше вашего действительного размера массива. Вы запускаете сетку N
x N
, но N
может быть больше, чем dimension
. Это означает, что некоторые из запущенных потоков могут попытаться получить доступ к матрицам (A
и B
) за пределами их допустимых размеров.
Вы можете исправить это с помощью "проверки потока" в вашем ядре, примерно так:
__global__ void CudaMM(float *A, float *B, int N)
{
int row = blockIdx.y*blockDim.y + threadIdx.y;
int col = blockIdx.x*blockDim.x + threadIdx.x;
if ((row < N) && (col < N)) {
float sum = 0.f;
for (int n = 0; n < N; ++n)
sum += A[row*N+n]*A[n*N+col];
B[row*N+col] = sum;
}
}
и вам нужно будет изменить свой вызов ядра на:
CudaMM<<<grid,threadBlock>>>(d_A,d_B,dimension);
Вы также можете захотеть выбрать размеры сетки на основе вашего фактического dimension
, а не фиксироваться на уровне 100*BLOCK_SIZE
, но это не обязательно, чтобы заставить код работать.