Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++에서 pthread 멀티스레드로 행렬 덧셈과 뺄셈 구현하기

이번 글에서는 멀티스레드 환경을 활용해 행렬의 덧셈과 뺄셈을 수행하는 방법을 알아보겠습니다. C/C++에서는 pthread(POSIX 스레드) 라이브러리를 사용하여 여러 개의 스레드를 동시에 실행할 수 있습니다.

기본 개념

두 개의 행렬 A와 B가 있으며, 각 행렬의 크기는 (m × n)입니다. 각 스레드는 행렬의 한 부분(행 그룹)을 담당하여 해당 영역의 덧셈 또는 뺄셈을 병렬로 처리합니다. 예제 코드에서는 3개의 코어를 가정하고, 각 스레드가 전체 행렬의 1/3씩 나누어 계산하도록 구현했습니다. 즉, 덧셈용 스레드 3개와 뺄셈용 스레드 3개, 총 6개의 스레드가 동시에 작업을 수행합니다.

이러한 방식은 행렬의 크기가 클수록 연산을 여러 코어에 분산시켜 실행 시간을 크게 단축할 수 있다는 장점이 있습니다.

예제 코드

#include<iostream>
#include <pthread.h>
#include <cstdlib>
#include <cstdint>
#define CORE 3
#define MAX 3
using namespace std;
int AMat[MAX][MAX] = {{10, 20, 30},
   {40, 50, 60},
   {70, 80, 50}
};
int BMat[MAX][MAX] = {{80, 60, 20},
   {30, 20, 15},
   {10, 14, 35}
};
pthread_t thread[CORE * 2];
int add[MAX][MAX], sub[MAX][MAX];
void* addMatrices(void* arg) {
   intptr_t core = (intptr_t)arg;
   // 각 스레드는 행렬 덧셈의 1/3을 계산
   for (int i = core * MAX / 3; i < (core + 1) * MAX / 3; i++) {
      for (int j = 0; j < MAX; j++) {
         add[i][j] = AMat[i][j] + BMat[i][j];
      }
   }
}
void* subtraction(void* arg) {
   intptr_t core = (intptr_t)arg;
   // 각 스레드는 행렬 뺄셈의 1/3을 계산
   for (int i = core * MAX / 3; i < (core + 1) * MAX / 3; i++) {
      for (int j = 0; j < MAX; j++) {
         sub[i][j] = AMat[i][j] - BMat[i][j];
      }
   }
}
void display(){
   cout << "Matrix A: " << endl;
   for(int i = 0; i < MAX; i++) {
      for(int j = 0; j < MAX; j++) {
         cout << AMat[i][j] << " ";
      }
      cout << endl;
   }
   cout << "\nMatrix B: " << endl;
   for(int i = 0; i < MAX; i++) {
      for(int j = 0; j < MAX; j++) {
         cout << BMat[i][j] << " ";
      }
      cout << endl;
   }
}
void displayRes(){
   cout << "\nAddition: " << endl;
   for(int i = 0; i < MAX; i++) {
      for(int j = 0; j < MAX; j++) {
         cout << add[i][j] << " ";
      }
      cout << endl;
   }
   cout << "\nSubtraction: " << endl;
   for(int i = 0; i < MAX; i++) {
      for(int j = 0; j < MAX; j++) {
         cout << sub[i][j] << " ";
      }
      cout << endl;
   }
}
main() {
   display();
   int step = 0;
   for (int i = 0; i < CORE; i++) {
      pthread_create(&thread[i], NULL, &addMatrices, (void*)step);
      pthread_create(&thread[i + CORE], NULL, &subtraction, (void*)step);
      step++;
   }
   for (int i = 0; i < CORE * 2; i++) {
      pthread_join(thread[i], NULL);
   }
   displayRes();
}

코드 설명

  • CORE: 사용할 스레드(코어) 수를 정의합니다. 여기서는 3으로 설정했습니다.
  • addMatrices(): 인자로 받은 번호(core)에 따라 자신이 맡은 행 범위만 계산하여 결과를 add 배열에 저장합니다.
  • subtraction(): 같은 방식으로 자신이 맡은 행 범위의 뺄셈 결과를 sub 배열에 저장합니다.
  • pthread_create(): 덧셈 스레드 3개와 뺄셈 스레드 3개를 생성하고, 각 스레드에 작업 번호(step)를 전달합니다.
  • pthread_join(): 모든 스레드의 작업이 끝날 때까지 메인 함수가 대기하도록 합니다. 이 과정이 없으면 연산이 완료되기 전에 결과가 출력될 수 있습니다.

실행 결과

Matrix A:
10 20 30
40 50 60
70 80 50
Matrix B:
80 60 20
30 20 15
10 14 35
Addition:
90 80 50
70 70 75
80 94 85
Subtraction:
-70 -40 10
10 30 45
60 66 15

마무리

이 예제는 pthread를 활용한 병렬 프로그래밍의 기초를 보여줍니다. 실제 대규모 행렬 연산에서는 이처럼 작업을 분할하여 여러 스레드에 배분하는 기법이 성능 향상에 매우 효과적입니다. 다만 스레드 간 데이터 경합(race condition)이 발생하지 않도록 각 스레드가 서로 다른 메모리 영역을 담당하도록 설계하는 것이 중요합니다. 위 코드에서는 각 스레드가 서로 다른 행을 처리하기 때문에 별도의 동기화 없이도 안전하게 동작합니다.