2013-05-19 7 views
1

업데이트!쿠다 매트릭스 곱하기가 틀린 답을줍니다.

현재 코드는 범위를 벗어난 메모리 액세스를 확인하지 않습니다. 내가 cuda memcheck를 실행할 때 메모리 액세스가 2 x 2의 행렬조차도 나쁘다 고합니다! 나는 어쨌든해서는 안되는 메모리에 액세스하고 있는데, 이것이 문제입니다!

는 경계 메모리 액세스 중 확인 ./(insert CUDA-memcheck를 실행하려면 아래 표시됨

이 행렬 곱셈 자체 내 코드입니다) 여기에 실행 :

dim3 block(32,32); 
dim3 grid((n+31)/32, (n+31)/32); 
matrixMul<<<grid,block>>>(d_C, d_A, d_B, n, k); 

kA 미만 및 kB는 값이있는 행렬입니다 (두 가지 모두 더 쉽게 만들 수 있습니다).

m, N, K는 KC 답변을 저장하는 행렬 내 정사각형 행렬

모든 동일한 수있다. 당신이 스레드의 그리드를 정의하는 방법에 따라

#ifndef _MATRIXMUL_KERNEL_H_ 
#define _MATRIXMUL_KERNEL_H_ 

#include <stdio.h> 

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k) 
{ 

    int tx = blockIdx.x * 32 + threadIdx.x; 
    int ty = blockIdx.y * 32 + threadIdx.y; 
    float value = 0; 

    for (int i=0;i<n;i++) 
    { 
     float elementA=kA[ty*n+i]; 
     float elementB=kB[i*k+tx]; 
     value += elementA*elementB; 
    } 

    kC[ty*n+tx] = value; 
} 

#endif // #ifndef _MATRIXMUL_KERNEL_H_ 
+0

메모리가 부족합니까? – Mechy

+0

변수'value'의 정의는 어디에 있습니까? for 루프 앞에 0을 초기화합니까? 이 코드는 컴파일하는 것처럼 보이지 않습니다. –

+0

@Robert Crovella 내 코드를 옮길 때 잘못된 변수 이름을 썼다. 그것은 "float 값"이어야하며 "float 값"이어야합니다. 내 프로그램에 "float value"가 있습니다. 10x10까지 작동한다면 그것이 내 기억일지도 모른다라고 생각하니? 10x10의 값은 행렬의 일부 행에 대한 값 또는 때로는 다른 값을 반환합니다 ... – Mechy

답변

2

,이 같은 커널 코드에 스레드 검사를 추가해야합니다 :

#ifndef _MATRIXMUL_KERNEL_H_ 
#define _MATRIXMUL_KERNEL_H_ 

#include <stdio.h> 

__global__ void matrixMul(float *kC, float *kA, float *kB, int n, int k) 
{ 

    int tx = blockIdx.x * 32 + threadIdx.x; 
    int ty = blockIdx.y * 32 + threadIdx.y; 

    if ((ty < n) && (tx < n)) { // add this line 
     float value = 0; 

     for (int i=0;i<n;i++) 
     { 
     float elementA=kA[ty*n+i]; 
     float elementB=kB[i*k+tx]; 
     value += elementA*elementB; 
     } 

     kC[ty*n+tx] = value; 
    } // add this line 
} 

#endif // #ifndef _MATRIXMUL_KERNEL_H_ 

그렇지 않으면 스레드 결과 손상됩니다 유효한 배열 배열 밖에. 잘못된 스레드가 없기 때문에 32x32의 배수 일을 처리 할 수 ​​있습니다. 이 경우 정확히 필요한 수의 스레드를 시작합니다. 그러나 다른 경우에는 여분의 스레드를 시작합니다. 이러한 여분의 스레드는 유효하지 않은 행렬 위치를 계산하도록 허용 된 경우 결과를 손상시킵니다.

+0

와우, 모든게 해결 됐어. 감사합니다. 따라서 기본적으로 커널 호출에 기반하여 스레드가 초기화되고 if 문없이 범위를 벗어난 경우에도 스레드가 실행됩니다. – Mechy

+0

예, 커널 호출로 그리드의 크기를 정의합니다. 커널이 그리드와 함께 실행되면, 모든 스레드가 실행되고, 어떤 시점에서 스레드 코드 (커널 코드) 실행을 시작합니다. –