2015-01-19 1 views
-2

두 행렬을 곱하는 간단한 함수가 있습니다.C 함수 호출로 인한 엄청난 오버 헤드

int main(int argc, char** argv) { 

    // timer structs 
    struct timeval ts, te, td; 
    float tser, tpar, diff; 
    int i, j, k; 

    printf("matrix size : %d x %d x %d\n", ni, nj, nk); 

    srand(0); 

    // initialization 
    for (i=0; i<ni; i++) { 
     for (k=0; k<nk; k++) { 
      A[i][k] = (float)rand()/RAND_MAX; 
     } 
    } 
    for (k=0; k<nk; k++) { 
     for (j=0; j<nj; j++) { 
      B[k][j] = (float)rand()/RAND_MAX; 
     } 
    } 

    gettimeofday(&ts, NULL); 
    for (i=0; i<ni; i++) { 
     for (j=0; j<nj; j++) { 
      Cans[i][j] = 0; 
      for (k=0; k<nk; k++) { 
       Cans[i][j] += A[i][k]*B[k][j]; 
      } 
     } 
    } 
    gettimeofday(&te, NULL); 
    timersub(&ts, &te, &td); 
    tser = fabs(td.tv_sec+(float)td.tv_usec/1000000.0); 

    gettimeofday(&ts, NULL); 
    mmul1(A, B, C); 
    gettimeofday(&te, NULL); 
    timersub(&ts, &te, &td); 
    tpar = fabs(td.tv_sec+(float)td.tv_usec/1000000.0); 

    // compare results 
    diff = compute_diff(C, Cans); 

    printf("Performance : %.2f GFlop/s (%.1fX)\n", 2.0*ni*nj*nk/tpar/1000000000, tser/tpar); 
    printf("Result Diff : %.3f\n", diff); 

    return 0; 
} 

내가 GCC의 -O3 플래그로 컴파일 오전 :

void mmul1(float A[ni][nk], float B[nk][nj], float C[ni][nj]) 
{ 
    int i, j, k; 
    for (i=0; i<ni; i++) { 
     for (j=0; j<nj; j++) { 
      C[i][j] = 0; 
      for (k=0; k<nk; k++) { 
       C[i][j] += A[i][k]*B[k][j]; 
      } 
     } 
    } 
} 

나는이처럼 보이는 주요 기능을 가지고있다.

테스트 할 때 mult의 서명에 static inline을 추가하면 512x512 행렬을 테스트 할 때 5 배의 속도 향상을 얻었습니다. 함수 호출의 오버 헤드는 곱셈에 비해 무시할 수 있어야합니다. 컴파일러가 다른 기계어 코드를 생성하는 이유는 무엇입니까? inlinemult없이이 성능 저하가 발생하는 이유는 무엇입니까? 이 기능을 inlinemain에 결과를 사용하지 않기 때문에

+0

매트릭스가 하드 코딩되었거나 사용자 입력에서 파생 되었습니까? 하드 코드 된 경우 사용자 입력에서 파생 된 동일한 동작을합니까? – Mehrdad

+0

행렬은 rand()로 채워집니다. – tomKPZ

+0

@MohitJain : 그 정보는 의문의 여지가 있습니다. – Clifford

답변

1

는 최적화 프로그램은 사용되는 어떤 부작용이 없는지 확인하고, 행렬의 곱셈 모든 코드를 제거하기 위해 무료로 할 수 있습니다.

gcc-S 플래그를 사용하여 생성 된 어셈블리 코드를 볼 수 있습니다.

+0

이것이 실제로 가능할 수도 있지만 - 주석에서 언급했지만 코드 조각은 많이 생략되어 있습니다 (많은'... '), 결과가 사용되지 않는다는 것을 어떻게 알 수 있습니까? – Clifford

+2

@Clifford OP가 질문을 수정하면 기다려야합니다. – juanchopanza

+1

동의합니다. 확실한 관심사는 포인터 앨리어싱입니다. 필자의 경험에 따르면 컴파일러가 관련 함수에서 포인터 앨리어싱 (예 :'restrict' 사용)을 취하도록 강요 할 수 있는지 확인하고 디버그 검사 ('assert (.) 매크로 사용)를 사용하여 강제 적용 할 수 있는지 확인해야합니다 .수치 해석 코드는 흔히 비슷한 구조 (즉, 'float' 또는'double'의 큰 n-dim 배열)를 많이 사용하기 때문에 일반적인 문제입니다. 이를 적용 할 수없는 경우 두 가지 버전의 기능이 필요하며 앨리어싱 검사를 스위치로 사용할 수 있습니다. – Persixty