2013-03-26 5 views
0

두 행렬의 결과를 세 번째 결과 행렬에 계속 추가하는 간단한 행렬 곱셈 프로그램을 작성하려고합니다. (필자는 측정하는 동안 본질적으로 GPU에 운동을 제공합니다. 별도의 장치로 전력 소비).CUDA 행렬 곱셈은 0을 고정시키고 행렬을 표시합니다.

많은 수의 반복을 지정하면 내 문제가 발생합니다. BLOCK_SIZE와 행렬 차원 값의 여러 조합을 사용해 보았습니다. 작은 행렬 차원에서는 반복 횟수를 늘릴 수 있지만 BLOCK_SIZE는 행렬 차원의 제곱근 (정사각형 행렬)이어야합니다.

이 경우 결과 오류는 39 초입니다 (반복 값에 관계없이 '너무 많음'인 경우) 동결 후 모든 제로 매트릭스 출력이 발생합니다. 흥미롭게도 20000의 반복으로 한 번 실행했는데 정상적으로 작동했습니다. 나는 그것을 다시 달리고 얼어 붙은 오류가났다.

아이디어가 있으십니까? 미리 감사드립니다!

커널 :

//******************************************************************** 
// matrixMultiplication_kernel.cu 
// 
// Kernel for a basic CUDA matrix multiplication program. 
//******************************************************************** 

#ifndef MATRIXMULTIPLICATION_KERNEL 
#define MATRIXMULTIPLICATION_KERNEL 

#define BLOCK_SIZE 16 // Set thread block size 
#define colsA 256  // Set matrix A column dimension 
#define rowsA 256  // Set matrix A row dimension 
#define colsB 256  // Set matrix B column dimension 
#define rowsB colsA // Set matrix B row dimension 
#define colsC colsB // Set matrix C column dimension 
#define rowsC rowsA // Set matrix C row dimension 

//-------------------------------------------------------------------- 
// matrixMultiplication() - Multiplies matrixA and matrixB, storing 
//       the result in device memory for matrixC. 
// 
// PRE: matrixA, matrixB, and matrixC are float pointers; numColsA 
//  numColsB are integers. 
// POST: The result of multiplying matrixA and matrixB is stored in 
//  matrixC. 
//-------------------------------------------------------------------- 
__global__ void matrixMultiplication(float * matrixA, float * matrixB, 
        float * matrixC, int numColsA, 
        int numColsB) { 

    /* Declare matrix-multplication holder value ouside of for loop */ 
    float val; 

    /* Set block and thread index positions */ 
    int blockX = blockIdx.x; 
    int blockY = blockIdx.y; 
    int threadX = threadIdx.x; 
    int threadY = threadIdx.y; 

    /* 
    Set starting and ending indices of the first sub-matrix of A 
    and sub-matrix size for matrix A 
    */ 
    int startA = numColsA * BLOCK_SIZE * blockY; 
    int endA = startA + numColsA - 1; 
    int subSizeA = BLOCK_SIZE; 

    /* 
    Set starting index of the first sub-matrix of B and sub-matrix 
    size for matrix B 
    */ 
    int startB = BLOCK_SIZE * blockX; 
    int subSizeB = BLOCK_SIZE * colsB; 

    /* Perform matrix multiplication 20000 times */ 
    for (int iteration = 0; iteration < 20000; iteration++) { 

     /* Loop through matrix A and matrix B's sub-matrices */ 
     for (int i = startA, j = startB; i <= endA; i += subSizeA, 
      j += subSizeB) { 

     /* 
      Declare shared memory arrays for matrix A and B 
      sub-matrices 
     */ 
     __shared__ float subA[BLOCK_SIZE][BLOCK_SIZE]; 
     __shared__ float subB[BLOCK_SIZE][BLOCK_SIZE]; 

     /* Fill sub-matrices */ 
     subA[threadY][threadX] = 
      matrixA[i + colsA * threadY + threadX]; 
     subB[threadY][threadX] = 
      matrixB[j + colsB * threadY + threadX]; 

     /* Ensure that the matrices are loaded */ 
     __syncthreads(); 

     /* Loop through the block */ 
     for (int k = 0; k < BLOCK_SIZE; ++k) { 

      /* Compute product of two matrix indices */ 
      val += subA[threadY][k] * subB[k][threadX]; 
     } 

     /* 
      Ensure completion before the next set of sub-matrices 
      begin computation 
     */ 
     __syncthreads(); 
    } 

    /* Set device memory for this sub-matrix */ 
    int position = colsB * BLOCK_SIZE * blockY + BLOCK_SIZE * blockX; 
    matrixC[position + colsB * threadY + threadX] = val; 
    } 
} 

#endif 

호스트 :

//******************************************************************** 
// matrixMultiplication.cu 
// 
// A basic CUDA matrix multiplication program. 
//******************************************************************** 

/* Include necessary libraries and kernel */ 
#include <stdlib.h> 
#include <stdio.h> 
#include <math.h> 
#include <matrixMultiplication_kernel.cu> 

/* Function declarations */ 
void fillMatrix(float * matrix, int numIndices); 

//************* 
// Main Program 
//************* 
int main(int argc, char** argv) { 

    /* Declare device memory */ 
    float * deviceA; 
    float * deviceB; 
    float * deviceC; 

    srand(2013); // Set random seed 

    /* Determine total number of indices in each matrix */ 
    unsigned int numIndicesA = colsA * rowsA; 
    unsigned int numIndicesB = colsB * rowsB; 
    unsigned int numIndicesC = colsC * rowsC; 

    /* Determine memory size of each matrix */ 
    unsigned int memoryA = sizeof(float) * numIndicesA; 
    unsigned int memoryB = sizeof(float) * numIndicesB; 
    unsigned int memoryC = sizeof(float) * numIndicesC; 

    /* Allocate memory for each matrix */ 
    float * matrixA = (float *) malloc(memoryA); 
    float * matrixB = (float *) malloc(memoryB); 
    float * matrixC = (float *) malloc(memoryC); 

    /* Set contents of matrices A and B (matrix C is all zeros) */ 
    fillMatrix(matrixA, numIndicesA); 
    fillMatrix(matrixB, numIndicesB); 

    /* Allocate device memory for each matrix */ 
    cudaMalloc((void **) &deviceA, memoryA); 
    cudaMalloc((void **) &deviceB, memoryB); 
    cudaMalloc((void **) &deviceC, memoryC); 

    /* Copy host memory to device memory for matrices A and B */ 
    cudaMemcpy(deviceA, matrixA, memoryA, cudaMemcpyHostToDevice); 
    cudaMemcpy(deviceB, matrixB, memoryB, cudaMemcpyHostToDevice); 

    /* Set thread count to BLOCK_SIZE x BLOCK_SIZE */ 
    dim3 tCount(BLOCK_SIZE, BLOCK_SIZE); 

    /* Set thread block count */ 
    dim3 tbCount((colsC/tCount.x), (rowsC/tCount.y)); 

    /* Run kernel */ 
    matrixMultiplication <<< tbCount, tCount >>> (deviceA, deviceB, 
          deviceC, colsA, 
          colsB); 

    /* Copy device memory to host memory for matrix C */ 
    cudaMemcpy(matrixC, deviceC, memoryC, cudaMemcpyDeviceToHost); 

    for(int i = 0; i < 256; i++) { 
     printf("%f ", matrixC[i]); 
    } 
    printf("\n"); 

    /* Free up host and device memory for each matrix */ 
    free(matrixA); 
    free(matrixB); 
    free(matrixC); 
    cudaFree(deviceA); 
    cudaFree(deviceB); 
    cudaFree(deviceC); 
} 

//-------------------------------------------------------------------- 
// fillMatrix - Assigns a random float value to each indice of the 
//    matrix. 
// 
// PRE: matrix is a pointer to a block of bytes in memory; numIndices 
//  is the number of indicies in the matrix being instantiated. 
// POST: Each index of the matrix has been filled with random float 
//  values. 
//-------------------------------------------------------------------- 
void fillMatrix(float * matrix, int numIndices) { 

    /* Loop through each index of the matrix */ 
    for (int i = 0; i < numIndices; ++i) { 

    /* 
     Assign a random float between 0 and 1 for this index of 
     the matrix 
    */ 
    matrix[i] = rand()/(float)RAND_MAX; 
    } 
} 
메이크

:

GCC = nvcc 
CUDA_INSTALL_PATH := /usr/local/cuda 
INCLUDES := -I. -I$(CUDA_INSTALL_PATH)/include 
CUDA_LIBS := -L$(CUDA_INSTALL_PATH)/lib -lcudart 

matrixMultiplication.o:  matrixMultiplication.cu 
        $(GCC) $(INCLUDES) -c matrixMultiplication.cu -o [email protected] 

matrixMultiplication:  matrixMultiplication.o 
     $(GCC) -o [email protected] matrixMultiplication.o $(CUDA_LIBS) 

clean: 
     $(RM) *.o *~ 
+0

냉각이 충분하지 않습니까? 이미 전력계를 연결했기 때문에 정사각형 행렬의 경우가 전력 소비가 가장 많은 경우인지 쉽게 확인할 수 있습니다. – tera

+0

저는 실제로 CUDA와 OpenCL을 비교하고 있습니다. 행렬 곱셈은 그 둘 사이의 일반적인 프로그램 일뿐입니다. –

+0

전용 GPU로 계산하고 있습니까? 그렇지 않으면 디스플레이 드라이버가 응답하지 않기 때문에 시스템 시간 초과 일 수 있습니다. (Windows에서는 제한 시간이 2 초입니다.) –

답변

1

문제가 해결! 커널의 긴 지속 시간 때문에 시스템 시간 초과 문제였습니다. 터미널 전용 모드를 전환하여이 문제를 피할 수있었습니다.

모든 도움 주셔서 감사합니다.