Skip to content
Extraits de code Groupes Projets
distributedmatrix.cpp 6,8 ko
Newer Older
  • Learn to ignore specific revisions
  • #include <iostream>
    #include <cassert>
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    #include "distributedmatrix.hpp"
    
    using namespace std;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    // Constructor to initialize the distributed matrix
    
    DistributedMatrix::DistributedMatrix(const Matrix& matrix, int numProcesses)
        : localData(0, 0){
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
        this->globalRows = matrix.numRows();
        this->globalCols = matrix.numCols();
        this->numProcesses = numProcesses;
        this->rank = 0;
        this->localCols = this->globalCols / this->numProcesses;
        this->startCol = 0;
    
    
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
        int remainingCols = globalCols % numProcesses;
    
        this->startCol = rank * localCols + min(rank, remainingCols);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        if (rank < remainingCols) {
    
            localCols++;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        }
    
        this->localData = Matrix(this->globalRows, this->localCols);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        for (int i = 0; i < this->globalRows; ++i) {
            for (int j = 0; j < this->localCols; ++j) {
    
                this->localData.set(i, j, matrix.get(i, this->startCol + j));
    
    // Copy constructor
    
    DistributedMatrix::DistributedMatrix(const DistributedMatrix& other)
        : localData(0, 0){
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        this->globalRows = other.globalRows;
        this->globalCols = other.globalCols;
        this->localCols = other.localCols;
        this->startCol = other.startCol;
        this->numProcesses = other.numProcesses;
        this->rank = other.rank;
    
        this->localData = other.localData;
    
    int DistributedMatrix::numRows() const {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        return this->globalRows;
    
    int DistributedMatrix::numCols() const {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        return this->globalCols;
    
    }
    
    double DistributedMatrix::get(int i, int j) const {
    
        if (j < startCol || j >= startCol + localCols) {
    
            throw std::out_of_range("Out of range.");
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        }
    
        return localData.get(i, j - startCol);
    
    }
    
    void DistributedMatrix::set(int i, int j, double value) {
    
        if (j < startCol || j >= startCol + localCols) {
    
            throw std::out_of_range("Out of range.)");
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
        }
    
        localData.set(i, j - startCol, value);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    int DistributedMatrix::globalColIndex(int localColIndex) const {
        return startCol + localColIndex;
    }
    
    int DistributedMatrix::localColIndex(int globalColIndex) const {
        if (globalColIndex >= startCol && globalColIndex < startCol + localCols) {
            return globalColIndex - startCol;
        }
    
        return -1;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    }
    
    int DistributedMatrix::ownerProcess(int globalColIndex) const {
    
        std::vector<int> localStartProcesses(numProcesses);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
        MPI_Allgather(&startCol, 1, MPI_INT, localStartProcesses.data(), 1, MPI_INT, MPI_COMM_WORLD);
    
        for (int p = 1; p < numProcesses; ++p) {
            if (globalColIndex >= localStartProcesses[p-1] && globalColIndex < localStartProcesses[p]) {
                return p - 1;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
            }
        }
    
        return numProcesses - 1;
        
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    }
    
    
    const Matrix& DistributedMatrix::getLocalData() const {
        return localData;
    
    }
    
    Matrix DistributedMatrix::gather() const {
    
    
        vector<double> localBuffer(localCols * globalRows);
    
        for (int i = 0; i < globalRows; ++i) {
            for (int j = 0; j < localCols; ++j) {
                localBuffer[i * localCols + j] = localData.get(i, j);
            }
        }
    
    
        vector<int> counts(numProcesses);
        vector<int> displacements(numProcesses);
    
        int remainingCols = globalCols % numProcesses;
        for (int p = 0; p < numProcesses; ++p) {
            int p_cols = (globalCols / numProcesses) + (p < remainingCols ? 1 : 0);
            counts[p] = globalRows * p_cols;
            displacements[p] = (p == 0) ? 0 : displacements[p - 1] + counts[p - 1];
        }
    
        vector<double> buffer(globalRows * globalCols);
    
    
        MPI_Allgatherv(
            localBuffer.data(),
            localCols * globalRows,
            MPI_DOUBLE,
            buffer.data(),
            counts.data(),
            displacements.data(),
            MPI_DOUBLE,
            MPI_COMM_WORLD
        );
    
        Matrix fullMatrix(globalRows, globalCols);
        int currentCol = 0;
        for (int p = 0; p < numProcesses; ++p) {
            int cols = (globalCols/numProcesses) + (p < remainingCols ? 1 : 0);
            for (int j = 0; j < cols; ++j) {
                for (int i = 0; i < globalRows; ++i) {
                    double val = buffer[displacements[p] + j + i * cols];
                    fullMatrix.set(i, currentCol, val);
    
                currentCol++;
    
        return fullMatrix;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    DistributedMatrix DistributedMatrix::apply(const std::function<double(double)> &func) const {
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
        DistributedMatrix result(*this);
    
        for (int i = 0; i < localData.numRows(); ++i) {
            for (int j = 0; j < localData.numCols(); ++j) {
                double value = localData.get(i, j);
                result.localData.set(i, j, func(value));
    
        return result;
    }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    DistributedMatrix DistributedMatrix::applyBinary(
        const DistributedMatrix& a,
        const DistributedMatrix& b,
        const std::function<double(double, double)>& func) {
    
        DistributedMatrix result(a);
    
        for (int i = 0; i < a.localData.numRows(); ++i) {
            for (int j = 0; j < a.localData.numCols(); ++j) {
                double valA = a.localData.get(i, j);
                double valB = b.localData.get(i, j);
                result.localData.set(i, j, func(valA, valB));
            }
        }
    
        return result;
    }
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    double DistributedMatrix::sum() const {
        
        double localSum = 0.0;
        for (int i = 0; i < globalRows; ++i) {
            for (int j = 0; j < localCols; ++j) {
                localSum += localData.get(i, j);
            }
        }
    
        double globalSum = 0.0;
    
        MPI_Allreduce(&localSum, &globalSum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
        return globalSum;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    }
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    DistributedMatrix multiply(const Matrix& left, const DistributedMatrix& right) {
        int globalRows = left.numRows();
        int globalCols = right.numCols();
        int localCols = right.localCols;
        
        Matrix resultMatrix(globalRows, globalCols);
    
        DistributedMatrix result(resultMatrix, right.numProcesses);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
        for (int i = 0; i < globalRows; ++i) {
            for (int j = 0; j < localCols; ++j) {
                double sum = 0.0;
                for (int k = 0; k < left.numCols(); ++k) {
                    sum += left.get(i, k) * right.localData.get(k, j);
                }
                result.localData.set(i, j, sum);
            }
        }
    
        return result;
    }
    
    
    Matrix DistributedMatrix::multiplyTransposed(const DistributedMatrix &other) const {
    
    
        Matrix result = (*this).localData * other.getLocalData().transpose();
    
        std::vector<double> buffer(this->globalRows * other.globalRows);
    
        MPI_Allreduce(
            result.getData().data(),
            buffer.data(),
            globalRows * other.globalRows,
            MPI_DOUBLE,
            MPI_SUM,
            MPI_COMM_WORLD
        );
    
        Matrix fullMatrix(globalRows, other.globalRows);
        
        for (int i = 0; i < globalRows; ++i) {
            for (int j = 0; j < other.globalRows; ++j) {
                fullMatrix.set(i, j, buffer[i * other.globalRows + j]); 
    
        return fullMatrix;
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé
    void sync_matrix(Matrix *matrix, int rank, int src) {
    
        MPI_Bcast(const_cast<double*>(matrix->getData().data()), matrix->numRows() * matrix->numCols(), MPI_DOUBLE, src, MPI_COMM_WORLD);
    
    JordanHanotiaux's avatar
    JordanHanotiaux a validé