Почему разделяемая память с помощью MPI_Win_allocated_shared фактически недоступна для всех?

#c #parallel-processing #mpi #remote-access #shared-memory

#c #параллельная обработка #mpi #удаленный доступ #разделяемая память

Вопрос:

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

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

int rank,size;
MPI_Comm_rank(MPI_COMM_WORLD, amp;rank);
MPI_Comm_size(MPI_COMM_WORLD, amp;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, amp;seller_buff, amp;win_seller);
    MPI_Win_allocate_shared(buff_size, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, amp;buyer_buff, amp;win_buyer);
}
else {
    int disp_unit;
    MPI_Win_allocate_shared(0, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, amp;seller_buff, amp;win_seller);
    MPI_Win_allocate_shared(0, sizeof(PWL), MPI_INFO_NULL,
                          MPI_COMM_WORLD, amp;buyer_buff, amp;win_buyer);
    MPI_Win_shared_query(win_seller, 0, amp;buff_size, amp;disp_unit, amp;seller_buff);
    MPI_Win_shared_query(win_buyer, 0, amp;buff_size, amp;disp_unit, amp;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 amp; f1, const PWL amp; f2);
    friend PWL minPWL (const PWL amp; f1, const PWL amp; f2);
    friend PWL operator/ (const PWL amp; 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 amp; v): lines(v) {
            check_lines();
        }
        PWL (const lines_vector amp; 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 amp; f1, const PWL amp; f2);
// minimum between piecewise linear functions
PWL minPWL (const PWL amp; f1, const PWL amp; f2);

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

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

#endif 
  

Комментарии:

1. Содержимое x_intersections вектора очень маловероятно в разделяемой памяти.

2. Почему? Будучи просто вектором double … у вас есть идеи о том, как заставить это работать?

3. Если вы знаете максимальный размер, то объявите его как массив (фиксированного размера) вместо вектора (неизвестного размера).

4. К сожалению, я этого не знаю, поскольку класс моделирует кусочно-линейные функции, которые могут иметь любое количество линейных частей