Почему общая память MPI_Win_allocated_shared на самом деле не доступна всем? - PullRequest
0 голосов
/ 23 марта 2019

Я реализую алгоритм, основанный на параллельных вычислениях MPI, но он также требует, чтобы все процессы имели доступ к двум общим буферам (например, двум матричным массивам), чей содержащийся тип данных является определяемым пользователем классом.MPI_Win_allocate_shared (который работал в моих испытаниях с массивом парных чисел или простым классом) не работает: один ранг фактически не может видеть, что другие ранги записывают в буферы, почему ??

std::pair <double, double> Options::BinomialPriceAmericanPut(void) {

int rank,size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);

// shared buffers to save data for seller and buyer
MPI_Win win_seller, win_buyer;
// size of the local window in bytes
MPI_Aint buff_size;

// pointers that will (locally) point to the shared memory
PWL *seller_buff;
PWL *buyer_buff;

// allocate shared memory
if (rank == 0) {
    buff_size = (N+2) * (L+1) * sizeof(PWL);
    MPI_Win_allocate_shared(buff_size, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, &seller_buff, &win_seller);
    MPI_Win_allocate_shared(buff_size, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, &buyer_buff, &win_buyer);
}
else {
    int disp_unit;
    MPI_Win_allocate_shared(0, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, &seller_buff, &win_seller);
    MPI_Win_allocate_shared(0, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, &buyer_buff, &win_buyer);
    MPI_Win_shared_query(win_seller, 0, &buff_size, &disp_unit, &seller_buff);
    MPI_Win_shared_query(win_buyer, 0, &buff_size, &disp_unit, &buyer_buff);
  }

// up- and down- move factors
double u = exp( sigma * sqrt(expiry/N) );

// cash accumulation factor
double r = exp( R*expiry / N );
u= 1.2;
r=1.18;

// initialize algorithm
int p(size);
int n = N + 2; // number of nodes in the current base level
int s = rank * ( n/p );
int e = (rank==p-1)? n: (rank+1) * ( n/p );
// each core works on e-s nodes in the current level

// compute u and z for both seller and buyer: payoff (0,0) at time N+1
for (int l=s; l<e; l++) {
    const double St = S0*pow (u, N+1-2*l);
    const double Sa = St * (1+k);
    const double Sb = St * (1-k);

    // compute functions
    PWL u_s( {Line(-Sa, 0), Line(-Sb,0)} );
    PWL u_b( {Line(-Sa, 0), Line(-Sb, 0)} );

    // fill buffers
    seller_buff[l] = u_s;   
    buyer_buff[l] = u_b;
}

MPI_Barrier(MPI_COMM_WORLD);
// PROVE: here is where I get the error: position [4] is filled by rank 1
// and rank 0 gives a segmentation fault when trying to access it
if (rank==0) {
    std::cout << "PROVA: " << std::endl << "\tAsk = " << 
seller_buff[4].valueInPoint(0) << std::endl << "\tBid = " << - 
buyer_buff[4].valueInPoint(0) << std::endl;
}

// etc, freeing windows at the end

Здесь класс PWL:

    #ifndef PWL_H_
#define PWL_H_

/* Class containing information about piecewise linear functions */

#include "Line.h"
#include <vector>
#include <iostream>

#define MINIMIZE_EPIGRAPH 0 // removes parallel lines keeping the one with highest intercept
#define MAXIMIZE_EPIGRAPH 1 // removes parallel lines keeping the one with lowest intercept


typedef std::vector<Line> lines_vector;

class PWL {
    friend PWL maxPWL (const PWL & f1, const PWL & f2);
    friend PWL minPWL (const PWL & f1, const PWL & f2);
    friend PWL operator/ (const PWL & f, double c);

    public:
        // vector of lines constituting the piecewise linear function
        lines_vector lines;
        // vector of abscissas of intersections among lines
        std::vector<double> x_intersections;

        // helper function giving the idx of the piece containing x
        size_t piece_of_interest (const double x ) const;

    public:
        // default constructor
        PWL () {
            lines.push_back( Line(0,0) );
            check_lines();
        }
        PWL (const int epi) {
            lines.push_back( Line(0,0) );
            check_lines(epi);
        }
        // constructor passing vector of lines: it computes x_intersections
        PWL (const lines_vector & v): lines(v) {
            check_lines();
        }
        PWL (const lines_vector & v, const int epi): lines(v) {
            check_lines(epi);
        }

        // evaluate function in a point
        double valueInPoint (const double x) const;

        // restrict function slopes within a given interval
        PWL restrict_slopes (const double l_bound, const double u_bound);

        // return the opposite of the piecewise linear function
        PWL opposite() const;

        // check if there are two consecutive parallel lines with different intercept
        // and compute x_intersections
        void check_lines (const int epigraph = MINIMIZE_EPIGRAPH);

        // getter
        lines_vector get_lines() const {return lines;}
        std::vector<double> get_intersections() const {return x_intersections;}

};

// maximum between piecewise linear functions
PWL maxPWL (const PWL & f1, const PWL & f2);
// minimum between piecewise linear functions
PWL minPWL (const PWL & f1, const PWL & f2);

// maximum between two lines in a given interval [a,b]
PWL maxLines (const Line & l1, const Line & l2, double a, double b);

// divide the function by a constant (operator overloading)
PWL operator/ (const PWL & f, double c);

#endif 
...