본문 바로가기
-----ETC-----/C++ 성능 최적화 및 고급 테크닉 시리즈

[C++ 성능 최적화 및 고급 테크닉] Day 24: 프로젝트: 고성능 매트릭스 라이브러리 개발 (1)

by cogito21_cpp 2024. 8. 1.
반응형

프로젝트 개요

고성능 매트릭스 라이브러리를 개발하는 프로젝트를 시작하겠습니다. 이 라이브러리는 행렬의 기본 연산(덧셈, 곱셈, 전치 등)을 고성능으로 구현하여 다양한 응용 프로그램에서 사용할 수 있도록 합니다.

 

프로젝트 목표

  1. 효율적인 데이터 구조: 행렬을 저장하기 위한 효율적인 데이터 구조를 설계합니다.
  2. 기본 연산 구현: 행렬 덧셈, 행렬 곱셈, 행렬 전치 등의 기본 연산을 구현합니다.
  3. 최적화: 루프 언롤링, 메모리 접근 최적화 등 다양한 최적화 기법을 적용합니다.
  4. 사용자 인터페이스: 사용자가 쉽게 사용할 수 있는 인터페이스를 제공합니다.

 

Step 1: 효율적인 데이터 구조 설계

먼저, 행렬을 저장하기 위한 효율적인 데이터 구조를 설계합니다. 행렬은 2차원 배열로 표현할 수 있으며, 이를 클래스 형태로 구현합니다.

Matrix 클래스 설계

Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <vector>
#include <iostream>
#include <stdexcept>

class Matrix {
private:
    std::vector<std::vector<double>> data;
    size_t rows, cols;

public:
    Matrix(size_t rows, size_t cols);
    double& operator()(size_t row, size_t col);
    const double& operator()(size_t row, size_t col) const;
    size_t getRows() const;
    size_t getCols() const;
    void print() const;
};

#endif // MATRIX_H

 

Matrix.cpp

#include "Matrix.h"

Matrix::Matrix(size_t rows, size_t cols) : rows(rows), cols(cols), data(rows, std::vector<double>(cols, 0.0)) {}

double& Matrix::operator()(size_t row, size_t col) {
    if (row >= rows || col >= cols) {
        throw std::out_of_range("Index out of range");
    }
    return data[row][col];
}

const double& Matrix::operator()(size_t row, size_t col) const {
    if (row >= rows || col >= cols) {
        throw std::out_of_range("Index out of range");
    }
    return data[row][col];
}

size_t Matrix::getRows() const {
    return rows;
}

size_t Matrix::getCols() const {
    return cols;
}

void Matrix::print() const {
    for (size_t i = 0; i < rows; ++i) {
        for (size_t j = 0; j < cols; ++j) {
            std::cout << data[i][j] << " ";
        }
        std::cout << std::endl;
    }
}

 

Step 2: 행렬 덧셈 구현

행렬 덧셈을 구현합니다. 두 행렬의 크기가 같아야 하며, 각 요소를 더하여 새로운 행렬을 반환합니다.

 

Matrix.h

Matrix operator+(const Matrix& lhs, const Matrix& rhs);

 

Matrix.cpp

#include "Matrix.h"

Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
    if (lhs.getRows() != rhs.getRows() || lhs.getCols() != rhs.getCols()) {
        throw std::invalid_argument("Matrices must have the same dimensions for addition");
    }

    Matrix result(lhs.getRows(), lhs.getCols());
    for (size_t i = 0; i < lhs.getRows(); ++i) {
        for (size_t j = 0; j < lhs.getCols(); ++j) {
            result(i, j) = lhs(i, j) + rhs(i, j);
        }
    }
    return result;
}

 

Step 3: 행렬 곱셈 구현

행렬 곱셈을 구현합니다. 두 행렬의 곱셈은 첫 번째 행렬의 열의 수와 두 번째 행렬의 행의 수가 같아야 합니다.

Matrix.h

Matrix operator*(const Matrix& lhs, const Matrix& rhs);

 

Matrix.cpp

#include "Matrix.h"

Matrix operator*(const Matrix& lhs, const Matrix& rhs) {
    if (lhs.getCols() != rhs.getRows()) {
        throw std::invalid_argument("Number of columns of the first matrix must be equal to the number of rows of the second matrix");
    }

    Matrix result(lhs.getRows(), rhs.getCols());
    for (size_t i = 0; i < lhs.getRows(); ++i) {
        for (size_t j = 0; j < rhs.getCols(); ++j) {
            for (size_t k = 0; k < lhs.getCols(); ++k) {
                result(i, j) += lhs(i, k) * rhs(k, j);
            }
        }
    }
    return result;
}

 

Step 4: 행렬 전치 구현

행렬 전치를 구현합니다. 행렬의 행과 열을 바꾼 새로운 행렬을 반환합니다.

 

Matrix.h

Matrix transpose(const Matrix& matrix);

 

Matrix.cpp

#include "Matrix.h"

Matrix transpose(const Matrix& matrix) {
    Matrix result(matrix.getCols(), matrix.getRows());
    for (size_t i = 0; i < matrix.getRows(); ++i) {
        for (size_t j = 0; j < matrix.getCols(); ++j) {
            result(j, i) = matrix(i, j);
        }
    }
    return result;
}

 

테스트 코드

main.cpp

#include <iostream>
#include "Matrix.h"

int main() {
    Matrix mat1(2, 3);
    Matrix mat2(2, 3);

    for (size_t i = 0; i < mat1.getRows(); ++i) {
        for (size_t j = 0; j < mat1.getCols(); ++j) {
            mat1(i, j) = i + j;
            mat2(i, j) = i * j;
        }
    }

    std::cout << "Matrix 1:" << std::endl;
    mat1.print();

    std::cout << "Matrix 2:" << std::endl;
    mat2.print();

    Matrix sum = mat1 + mat2;
    std::cout << "Sum of Matrix 1 and Matrix 2:" << std::endl;
    sum.print();

    Matrix mat3(3, 2);
    for (size_t i = 0; i < mat3.getRows(); ++i) {
        for (size_t j = 0; j < mat3.getCols(); ++j) {
            mat3(i, j) = i + j + 1;
        }
    }

    std::cout << "Matrix 3:" << std::endl;
    mat3.print();

    Matrix product = mat1 * mat3;
    std::cout << "Product of Matrix 1 and Matrix 3:" << std::endl;
    product.print();

    Matrix transposed = transpose(mat1);
    std::cout << "Transposed Matrix 1:" << std::endl;
    transposed.print();

    return 0;
}

 

이제 스물네 번째 날의 학습을 마쳤습니다. 고성능 매트릭스 라이브러리 개발 프로젝트의 첫 단계를 통해 기본적인 데이터 구조 설계와 행렬의 기본 연산을 구현했습니다.

질문이나 피드백이 있으면 언제든지 댓글로 남겨 주세요. 내일은 "프로젝트: 고성능 매트릭스 라이브러리 개발 (2)"에 대해 학습하겠습니다.

반응형