Tengo el siguiente código de multiplicación de matrices, implementado con CUDA 3.2 y VS 2008. Me estoy ejecutando en Windows Server 2008 r2 enterprise. Estoy ejecutando una Nvidia GTX 480. El siguiente código funciona bien con los valores de "Ancho" (ancho de la matriz) de hasta aproximadamente 2500 o menos.CUDA Interrupciones de multiplicación de matrices para matrices grandes
int size = Width*Width*sizeof(float);
float* Md, *Nd, *Pd;
cudaError_t err = cudaSuccess;
//Allocate Device Memory for M, N and P
err = cudaMalloc((void**)&Md, size);
err = cudaMalloc((void**)&Nd, size);
err = cudaMalloc((void**)&Pd, size);
//Copy Matrix from Host Memory to Device Memory
err = cudaMemcpy(Md, M, size, cudaMemcpyHostToDevice);
err = cudaMemcpy(Nd, N, size, cudaMemcpyHostToDevice);
//Setup the execution configuration
dim3 dimBlock(TileWidth, TileWidth, 1);
dim3 dimGrid(ceil((float)(Width)/TileWidth), ceil((float)(Width)/TileWidth), 1);
MatrixMultiplicationMultiBlock_Kernel<<<dimGrid, dimBlock>>>(Md, Nd, Pd, Width);
err = cudaMemcpy(P, Pd, size, cudaMemcpyDeviceToHost);
//Free Device Memory
cudaFree(Md);
cudaFree(Nd);
cudaFree(Pd);
Cuando me puse el "Ancho" a 3000 o mayor, me sale el siguiente error después de una pantalla en negro:
busqué en línea y vi que algunas personas tienen este problema debido a que el organismo de control estaba matando al núcleo después de que se cuelga por más de 5 segundos. Traté de editar el "TdrDelay" en el registro y esto retrasó el tiempo antes de que apareciera la pantalla en negro y el mismo error. Entonces concluí que este no era mi problema.
I depurado en mi código y encontraron esta línea de ser el culpable:
err = cudaMemcpy(P, Pd, size, cudaMemcpyDeviceToHost);
Esto es lo que uso para devolver mi conjunto de resultados desde el dispositivo después de mi función de multiplicación de la matriz del núcleo se llama. Todo hasta este punto parece funcionar bien. Creo que estoy asignando la memoria correctamente y no puedo entender por qué sucede esto. Pensé que tal vez no tenía suficiente memoria en mi tarjeta para esto, pero ¿no debería haber devuelto cudaMalloc un error? (Confirmé que no lo hice durante la depuración).
¡Cualquier idea/ayuda sería muy apreciada! ... Muchas gracias muchachos !! código
Kernel:
//Matrix Multiplication Kernel - Multi-Block Implementation
__global__ void MatrixMultiplicationMultiBlock_Kernel (float* Md, float* Nd, float* Pd, int Width)
{
int TileWidth = blockDim.x;
//Get row and column from block and thread ids
int Row = (TileWidth*blockIdx.y) + threadIdx.y;
int Column = (TileWidth*blockIdx.x) + threadIdx.x;
//Pvalue store the Pd element that is computed by the thread
float Pvalue = 0;
for (int i = 0; i < Width; ++i)
{
float Mdelement = Md[Row * Width + i];
float Ndelement = Nd[i * Width + Column];
Pvalue += Mdelement * Ndelement;
}
//Write the matrix to device memory each thread writes one element
Pd[Row * Width + Column] = Pvalue;
}
también tengo esta otra función que utiliza la memoria compartida, y también da el mismo error:
Llamar:
MatrixMultiplicationSharedMemory_Kernel<<<dimGrid, dimBlock, sizeof(float)*TileWidth*TileWidth*2>>>(Md, Nd, Pd, Width);
código del núcleo:
//Matrix Multiplication Kernel - Shared Memory Implementation
__global__ void MatrixMultiplicationSharedMemory_Kernel (float* Md, float* Nd, float* Pd, int Width)
{
int TileWidth = blockDim.x;
//Initialize shared memory
extern __shared__ float sharedArrays[];
float* Mds = (float*) &sharedArrays;
float* Nds = (float*) &Mds[TileWidth*TileWidth];
int tx = threadIdx.x;
int ty = threadIdx.y;
//Get row and column from block and thread ids
int Row = (TileWidth*blockIdx.y) + ty;
int Column = (TileWidth*blockIdx.x) + tx;
float Pvalue = 0;
//For each tile, load the element into shared memory
for(int i = 0; i < ceil((float)Width/TileWidth); ++i)
{
Mds[ty*TileWidth+tx] = Md[Row*Width + (i*TileWidth + tx)];
Nds[ty*TileWidth+tx] = Nd[(ty + (i * TileWidth))*Width + Column];
__syncthreads();
for(int j = 0; j < TileWidth; ++j)
{
Pvalue += Mds[ty*TileWidth+j] * Nds[j*TileWidth+tx];
}
__syncthreads();
}
//Write the matrix to device memory each thread writes one element
Pd[Row * Width + Column] = Pvalue;
}
¿Puedes publicar el código del núcleo por favor? – Tom
EDITAR: Agregó el código Kernel – ntsue
EDITAR: Se agregaron las funciones de código kernel – ntsue