본문 바로가기
프로그래밍/병렬프로그래밍

[OpenMP] 행렬-벡터 곱 연산

by 별준 2021. 11. 25.

References

  • An Introduction to Parallel Programming

Contents

  • Matrix-vector multiplication

[MPI] 행렬 - 벡터 곱 연산 + 성능 평가

[pthread] 행렬 - 벡터 곱 연산 (+ 캐시 일관성, 거짓 공유)

MPI와 Pthreads에서 구현해본 행렬-벡터 곱 연산과 마찬가지로 OpenMP에서도 행렬-벡터 곱 연산 코드를 작성해봤습니다.

void Omp_mat_vec_mul(double A[], double x[], double y[], int m, int n, int thread_count)
{
    double start, finish, temp;
    start = omp_get_wtime();
#pragma omp parallel for num_threads(thread_count) \
    default(none) private(temp) shared(A, x, y, m, n)
    for (int i = 0; i < m; i++) {
        y[i] = 0.0;
        for (int j = 0; j < n; j++) {
            //y[i] += A[i*n + j] * x[j];
            temp = A[i*n + j] * x[j];
            y[i] += temp;
        }
    }
    finish = omp_get_wtime();

    printf("Elapsed time = %f seconds\n", finish - start);
}

OpenMP에서 행렬-벡터 곱은 위 코드처럼 구현할 수 있습니다. 전체 코드는 아래 링크에서 확인하실 수 있습니다.

https://github.com/junstar92/parallel_programming_study/blob/master/OpenMP/12_omp_mat_vec_mul.c

 

GitHub - junstar92/parallel_programming_study

Contribute to junstar92/parallel_programming_study development by creating an account on GitHub.

github.com

내용은 pthread 포스트에서 설명한 것과 동일하므로 자세한 설명은 넘어가고, 한 가지만 집고 마무리하도록 하겠습니다.

 

pthread 포스트에서 설명한 캐시 일관성이나 거짓 공유는 OpenMP에서도 동일합니다. 따라서 설명했던 문제점들이 똑같이 발생할 수 있습니다. 따라서 프로그램을 프로파일링 해보면 거짓 공유에 의해서 read-miss나 write-miss가 발생합니다. 이는 프로그램의 성능을 매우 저하시킬 수 있는데, line 10에 제가 주석친 부분을 살펴보겠습니다. 매트릭스와 벡터의 요소들의 곱을 y의 요소에 바로 누적시키고 있습니다. 

주석친 부분의 코드로 프로그램을 컴파일하고 실행한 결과는 다음과 같습니다.

스레드 행렬 크기
8,000,000 x 8 8,000 x 8,000 8 x 8,000,000
1 0.267 0.282 0.284
2 0.136 0.154 0.213
4 0.091 0.101 0.293

pthread때와 유사한 패턴을 보여주고 있습니다.

 

이제 주석친 부분이 아닌 temp에 연산 결과를 누적하고 마지막에 y의 요소에 temp값을 복사하는 코드로 프로그램을 수행해보면,

스레드 행렬 크기
8,000,000 x 8 8,000 x 8,000 8 x 8,000,000
1 0.213 0.179 0.182
2 0.105 0.115 0.261
4 0.056 0.046 0.239

8 x 8,000,000 행렬에서는 아무래도 캐시 미스가 많이 발생하여 스레드가 많을수록 성능이 오히려 더 안좋아지지만, 바로 y에 연산 결과를 누적하는 코드보다는 성능이 좋다는 것을 볼 수 있습니다.

 

이처럼 다른 스레드에 의해 업데이트된 내용이 다른 스레드의 캐시 라인에 영향을 주지 않도록 더미(dummy)를 만들어서 곱셈 연산을 수행하면 성능을 더 향상시킬 수 있습니다.

 

 

댓글