2017-09-17 3 views
0

Je travaille sur un projet où j'ai créé une classe à l'aide de Array Eigen comme celui-ciMPI dérivé datatype pour Eigen Tableau

class Cartesian{ 
    public: 
     double x() const { return r_(0); } 
     double y() const { return r_(1); } 
     double z() const { return r_(2); } 
    private: 
     Eigen::Array3d r_; 
} 

Eigen::Array<Cartesian, Eigen::Dynamic, 1> Cart_Array(10); 

Alors maintenant, je veux envoyer Cart_Array en utilisant MPI_Send de Proc 0 à Proc 1. Quelle est la meilleure façon de le faire? Je veux créer un type de données MPI dérivé; par exemple, Cart_Type, puis l'envoyer comme

MPI_Send(&Cart_Array, 10, Cart_Type, 1, TAG, MPI_COMM_WORLD). 

Je sais comment créer MPI types dérivés pour des choses simples à l'aide MPI_Type_create_struct, etc. Mais je ne sais pas comment faire pour le cas je l'ai montré. Pourriez-vous s'il vous plaît me montrer. Si possible, je voudrais éviter d'autres bibliothèques telles que Boost.

: EDITS

J'ai posé cette question parce que je voulais éviter d'utiliser l'approche de sérialisation. Et c'est parce que cela fait partie d'un vaste programme qui met l'accent sur l'efficacité.

Répondre

0

Vous devriez faire quelque chose comme ci-dessous. Juste sérialiser un ou plusieurs Cartesian en vecteur de doubles, envoyer et recevoir ces doubles et désérialiser. J'espère que cela compile, parce que je viens de taper ceci sur une machine sans MPI. Je n'ai pas installé Eigen, mais vous avez l'idée.

class Cartesian{ 
public: 
    double x() const { return r_(0); } 
    double y() const { return r_(1); } 
    double z() const { return r_(2); } 
    std::vector<double> const& r() const { return r_; }; 
    Cartesian* operator=(std::vector<double> const& r) {r_ = r;} 
private: 
    std::vector<double> r_; 
    //Eigen::Array3d r_; 
}; 

// Send vector of Cartesian 
void sendData(std::vector<Cartesian> const& v) { 
    std::vector<double> data; 
    for (auto const& i : v) { 
    data.insert(data.end(), v.r().begin(), v.r().end()); 
    } 
    MPI_Send(data.begin(), data.size(), MPI_DOUBLE, 0, 1, MPI_COMM_WORLD); 
} 

// Receive vector of Cartesian 
std::vector<Cartesian> recvData() { 

    int n; 
    MPI_Status status; 
    MPI_Probe(0, 0, MPI_COMM_WORLD, &status); // Incoming? 
    MPI_Get_count(&status, MPI_INT, &n); // Number of incoming 

    std::vector<Cartesian> v; 
    if (n>0) { 
    std::vector<double>(n); 
    MPI_Recv(n.begin(), n, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    v.resize(n/3); 
    int i = 0; 
    for (auto i : v) { 
     i.r(*b.begin()+3*i); 
     ++i; 
    } 
    } 
    return v; 

} 

int main() { 

    MPI_Init(NULL, NULL); 

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

    std::vector<Cartesian> data; 
    if (rank == 0) { 
    data.resize(1000); 
    sendData(data); 
    } else { 
    data = recvData(); 
    } 

    MPI_Finalize(); 

} 
+0

Merci. J'ai effectivement utilisé la sérialisation dans ma version précédente du code, mais cela implique de copier et de déplacer des données. Je veux utiliser le type de données dérivé pour espérer que ce soit plus efficace, puisque le code que j'ai montré fait partie d'un grand programme de calcul haute performance. Une raison particulière pour laquelle vous utilisez std :: vector au lieu de Eigen, sans compter que vous ne l'avez pas? – Bill

+0

Quel réseau utilisez-vous? Si vous n'êtes pas sur Infiniband ne commencez même pas à réfléchir sur cette route. Aussi, si j'étais vous, je profilerais le code et découvrirais, si vous n'optimisez pas 0.001%. Je doute fortement que par rapport au temps de mise en réseau et de calcul, vous serez en mesure de mettre une valeur sur la sérialisation. –

+0

J'utilise le code sur plusieurs plates-formes, certaines d'entre elles utilisent Infiniband. Merci de votre aide. – Bill