2013-07-01 4 views
1

블록 행렬 곱셈을 재귀 적으로 구현하려고합니다. 그것은 2 × 2의 행렬을 위해 잘 작동되지만, 4 × 4와 같은 크기로 증가하고 답변 루프 3의재귀 블록 행렬 곱셈

결과 크게 다를 재귀

1.53 0.89 0.53 1.33 
1.75 1.09 0.72 1.17 
1.78 1.43 0.57 1.69 
1.73 1.04 0.62 1.51 

결과

1.34 1.49 0.30 1.45 
2.02 1.93 0.79 1.30 
2.70 2.75 0.87 2.21 
1.81 1.84 0.59 1.47 

만약 블록의 양 행렬 내에서 4보다 큰 경우 블록을 4 개의 큰 블록으로 나누고 제곱근을 가져 와서 새로운 차원을 얻은 다음 8 개의 재귀 호출을 만듭니다.

void myRecMat(float** MatrixA, float** MatrixB, float** MatrixC, int srA, int scA, int srB, int scB, int srC, int scC, int blocks,int dim){ 
if(blocks > 4) 
{ blocks=blocks/4; 
     int newDim = dim/2; 

     myRecMat(MatrixA,MatrixB,MatrixC, srA,scA,srB,scB,srC,scC,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA,scA+newDim,srB+newDim,scB,srC,scC,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA,scA,srB,scB+newDim,srC,scC+newDim,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA,srB,scB,srC+newDim,scC,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim); 
     myRecMat(MatrixA,MatrixB,MatrixC, srA+newDim,scA+newDim,srB+newDim,scB+newDim,srC+newDim,scC+newDim,blocks,newDim); }     
else 
{ 
int i,j,k,endR,endC; 
endR=srC+dim; 
endC=scC+dim; 


for(i=srC; i< endR; i++) 
     for(j=scC;j< endC;j++) 
      for(k=0; k<newDim; k++) 
        c[i][j] += a[i][k]*b[k][j]; 

} 
} 

sr과 sc는 행과 열을 시작하는 데 사용됩니다. 간격은 맞아야합니다. 그래서 저는 솔직히 여기서 리드를 벗어납니다. 고맙습니다.

+0

함수 선언 – banarun

+0

추가 선언을 추가하십시오. – user2243369

답변

0

코드를 컴파일하고 신중하게 디버깅했습니다. 2^k * 2^k의 행렬에서만이 함수를 사용하려는 경우이 두 가지 수정이 도움이됩니다.

첫째 :

for(i=srC; i< endR; i++) { 
    for(j=scC;j< endC;j++) { 
     for(k=0; k<newDim; k++) 
      /*c[i][j] += a[i][k]*b[k][j];*/ 
      c[i][j] += a[i][scA+k] * b[srB+k][j]; 
    } 
} 

둘째 :

myRecMat(MatrixA,MatrixB,MatrixC,srA,scA,srB,scB,srC,scC,blocks,newDim); 
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB,srC,scC,blocks,newDim); 
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA,srB,scB+newDim,srC,scC+newDim,blocks,newDim); 
/*myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB,srC+newDim, scC,blocks,newDim);*/ 
myRecMat(MatrixA,MatrixB,MatrixC,srA,scA+newDim,srB+newDim,scB+newDim,srC, scC+newDim,blocks,newDim); 
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA,srB,scB,srC+newDim,scC,blocks,newDim); 
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB+newDim,scB,srC+newDim,scC,blocks,newDim); 
/*myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim);*/ 
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA,srB,scB+newDim,srC+newDim,scC+newDim,blocks,newDim); 
myRecMat(MatrixA,MatrixB,MatrixC,srA+newDim,scA+newDim,srB+newDim,scB+newDim,srC+newDim,scC+newDim,blocks,newDim); 
+0

개조 선생님들과 테스트를 거쳤습니다. 첫 번째는 예배 였고 두 번째는 아니 었습니다. 나는 두 번째 부분에 필요한 mod를 만들었다. 첫 번째와 관련해서는 a의 행과 b의 열에 대한 오프셋이 필요한 것처럼 보입니다. 따라서 숫자가 합산되지 않은 이유는 무엇입니까? 두 번째 부분에서는 매트릭스가 4X4에 대해 표시된대로 작동했기 때문에 2, 8X8의 또 다른 힘을 부딪 혔을 때 모서리를 올바르게했고 중간 부분은 주석 처리 된 부분 때문에 누락되었습니다. 어쨌든 도움 주셔서 감사합니다. – user2243369

+0

흠 ... 나는 좀 더 큰 매트릭스 (8x8, 16x16, 무작위로 생성 된 값들)로 수정 된 코드를 다시 시험해 보았고, 온라인 매트릭스 계산기로 결과를 확인했다. 행/열 정의에 문제가있을 수 있습니다. – dexjq23

+0

k-loop 조건이 k shams

0

여기서 문제는 메서드 구현과 관련이 없지만 부동 소수점 연산의 정밀도가 떨어지는 것입니다. 때때로 이러한 부정확성은 무시할 만하다고 생각할 수도 있지만, 트리플 중첩 루프와 같은 부동 소수점 변수에 대한 집중적 인 연산을 수행 할 때 이러한 부정확 함이 중요하게됩니다.

이 문제를 해결할 수있는 한 가지 방법은 부동 소수점 숫자를 소수 자릿수를 "잃어 버릴"크기로 조절하는 것입니다. 예를 들어, 행렬에 10 진수가 2 자리 이상인 숫자가 없다는 것을 알고있는 경우 행 수를 모두 100으로 곱하고 정수 표현을 얻습니다. 그런 다음 정수에 대한 연산 (정확한)을 수행하고 결과에서 부동 소수점 표현을 얻은 다음 100으로 나눕니다.

희망이 있습니다.

+0

사실이면서 생각은 내 마음을 넘어 섰다. 나는 3 for 반복문을 통해 반복적으로 행렬을 곱하거나 반복적으로 나누어서 행렬을 곱하기로 결정했는지에 대해 이렇게 대답을 바꾸지 않을 것이라고 생각한다. – user2243369

+0

부동 소수점을 스케일링하는 것은 어리석은 방법입니다. 특히 행렬 곱셈이 집합 Q에서 닫힌 연산임을 고려할 때 (행렬 구성 요소가 Q에도 있다고 가정 할 때). 분자/분모가있는 객체를 사용하고 분모를 확장하여 나눗셈을 수행하는 것이 좋습니다. 최종 결과는 정밀도 손실이 없으며 부동 소수점 값 사용으로 인한 손실보다 훨씬 낫습니다. – ThePyroEagle