2017-11-15 5 views
0

openMP에 대해 조금 배우고 여기에 두 행렬을 곱하기 위해 사용하려고합니다.행렬 곱셈 (OpenMP) 최적화 - C

void matrix_multiply(matrix *A, matrix *B, matrix *C) { 

    #pragma omp parallel 
    { 
     #pragma omp for 
     for(int i = 0; i < A->dim.rows; i++) { 
      for(int j = 0; j < B->dim.cols; j++) { 
       C->data[i][j] = 0; 
       for (int k = 0; k < A->dim.cols; k++) { 
       C->data[i][j] += A->data[i][k] * B->data[k][j]; 
       } 
      } 
     } 
    } 
} 

typedef struct shape { 
    int rows; 
    int cols; 
} shape; 

typedef struct matrix { 
    shape dim; 
    float** data; 
} matrix; 

아직 조금 새롭기 때문에 성능을 향상시키기 위해 간단한 변경 사항이 있습니까? 아니면 이미 완료 했습니까? 또한 감소를 사용하지 않음으로써 모든 데이터 경주에 참여하고 있습니까?

답변

2

현재 구현을 향상시킬 수 없을 수도 있습니다. 이 시점에서 컴파일러와 캐시 사용량이 내려갑니다. 재미있는 점은 GCC가 곱셈을 벡터화 (즉, SIMD 사용)하기 위해 두 개의 루프를 교환해야한다는 흥미로운 점이 있습니다 (here by Intel). 매우 큰 행렬의 경우 행렬을 줄이 아닌 블록으로 나누는 것이 좋습니다. 이로 인해 복잡성과 오버 헤드가 발생하지만 캐시 사용을 향상시킬 수 있습니다.

축소 절은 하나의 변수를 여러 스레드로 합하는 경우에만 필요합니다.이 경우는 k 이상의 값을 합한 값이기 때문에 여기서는 그렇지 않습니다.

마지막으로 내 의견으로는 다소 청소기 보이는 단일 한

#pragma omp parallel for 

하여이 개 지침을 대체 할 수 있습니다 (그러나 이것은 완전히 개인적인).

+0

교육적 연습 (즉, OpenMP 사용 방법 학습) 인 경우에는 문제가되지 않습니다. 고성능 행렬 곱셈을 원하면 지금 중지하십시오. 대신에 더 많은 최적화 (예 : 캐시 차단)가있는 Intel MKL과 같은 라이브러리를 찾아보십시오. 사실, 순진한 병렬 처리의 성능을 MKL의 성능과 비교하는 것이 흥미로울 수 있습니다 ... –