Nano Hash - криптовалюты, майнинг, программирование

Boost mpi зависает

У меня есть простая асинхронная программа обмена сообщениями, как показано ниже. Я запускаю его на двух ПК с 16 процессами. Эти процессы связаны по торрусу в виде матрицы 4x4. Итак, в начале функции main вы увидите, кто является соседями процесса. То, что я пытаюсь сделать, это реализовать алгоритм контрольных точек. Таким образом, каждый процесс отправляет сообщение всем своим соседям, когда i = 5 или 10 (предположим, что i — это время). И когда процесс получает сообщение, он запускает новый irecv для того же процесса. Но если я равен 10, он не запускает irecv, потому что после этого сообщения не будут получены. В конце программы все процессы ждут неполученных сообщений.

/* Demo_01_Main.cpp */

#include <boost/mpi.hpp>
#include <boost/serialization/string.hpp>
#include <string>
#include <iostream>
#include <fstream>
#include <map>

using namespace std;

class Packet{
    friend class boost::serialization::access;
private:
    int receiver;
    int sender;
    int data;

public:
    Packet(){
        receiver = 0;
        sender = 0;
        data = 0;
    }

    Packet(int receiver, int sender, int data){
        this->receiver = receiver;
        this->sender = sender;
        this->data = data;
    }

    ~Packet(){}

    int getData() {
        return data;
    }

    void setData(int data) {
        this->data = data;
    }

    int getReceiver() {
        return receiver;
    }

    void setReceiver(int receiver) {
        this->receiver = receiver;
    }

    int getSender() {
        return sender;
    }

    void setSender(int sender) {
        this->sender = sender;
    }

    template<class Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & receiver;
        ar & sender;
        ar & data;
    }

    string toString(){
        stringstream ss;
        ss << "Packet = [Data: " << data << ", Receiver: " << receiver << ", Sender: " << sender << "]";
        return ss.str();
    }
};

int rank;

void log(string str){
    ofstream outfile;
    stringstream logFileName;
    logFileName << "log_" << rank << ".txt";
    outfile.open(logFileName.str().c_str(), std::ios_base::app);
    outfile << str;
    outfile.close();
}

int main(int argc, char* argv[]){
    map<int, boost::mpi::request> mpiReceiveRequest;
    map<int, boost::mpi::request> mpiSendRequest;
    map<int, Packet *> receivedData;
    vector<int> neighbors;

    boost::mpi::environment env(argc, argv);
    boost::mpi::communicator world;

    rank = world.rank();

    if(rank == 0){
        neighbors.push_back(1);
        neighbors.push_back(3);
        neighbors.push_back(4);
        neighbors.push_back(5);
        neighbors.push_back(7);
        neighbors.push_back(12);
        neighbors.push_back(13);
        neighbors.push_back(15);
    }
    else if(rank == 1){
        neighbors.push_back(0);
        neighbors.push_back(2);
        neighbors.push_back(4);
        neighbors.push_back(5);
        neighbors.push_back(6);
        neighbors.push_back(12);
        neighbors.push_back(13);
        neighbors.push_back(14);
    }
    else if(rank == 2){
        neighbors.push_back(1);
        neighbors.push_back(3);
        neighbors.push_back(5);
        neighbors.push_back(6);
        neighbors.push_back(7);
        neighbors.push_back(13);
        neighbors.push_back(14);
        neighbors.push_back(15);
    }
    else if(rank == 3){
        neighbors.push_back(0);
        neighbors.push_back(2);
        neighbors.push_back(4);
        neighbors.push_back(6);
        neighbors.push_back(7);
        neighbors.push_back(12);
        neighbors.push_back(14);
        neighbors.push_back(15);
    }
    else if(rank == 4){
        neighbors.push_back(0);
        neighbors.push_back(1);
        neighbors.push_back(3);
        neighbors.push_back(5);
        neighbors.push_back(7);
        neighbors.push_back(8);
        neighbors.push_back(9);
        neighbors.push_back(11);
    }
    else if(rank == 5){
        neighbors.push_back(0);
        neighbors.push_back(1);
        neighbors.push_back(2);
        neighbors.push_back(4);
        neighbors.push_back(6);
        neighbors.push_back(8);
        neighbors.push_back(9);
        neighbors.push_back(10);
    }
    else if(rank == 6){
        neighbors.push_back(1);
        neighbors.push_back(2);
        neighbors.push_back(3);
        neighbors.push_back(5);
        neighbors.push_back(7);
        neighbors.push_back(9);
        neighbors.push_back(10);
        neighbors.push_back(11);
    }
    else if(rank == 7){
        neighbors.push_back(0);
        neighbors.push_back(2);
        neighbors.push_back(3);
        neighbors.push_back(4);
        neighbors.push_back(6);
        neighbors.push_back(8);
        neighbors.push_back(10);
        neighbors.push_back(11);
    }
    else if(rank == 8){
        neighbors.push_back(4);
        neighbors.push_back(5);
        neighbors.push_back(7);
        neighbors.push_back(9);
        neighbors.push_back(11);
        neighbors.push_back(12);
        neighbors.push_back(13);
        neighbors.push_back(15);
    }
    else if(rank == 9){
        neighbors.push_back(4);
        neighbors.push_back(5);
        neighbors.push_back(6);
        neighbors.push_back(8);
        neighbors.push_back(10);
        neighbors.push_back(12);
        neighbors.push_back(13);
        neighbors.push_back(14);
    }
    else if(rank == 10){
        neighbors.push_back(5);
        neighbors.push_back(6);
        neighbors.push_back(7);
        neighbors.push_back(9);
        neighbors.push_back(11);
        neighbors.push_back(13);
        neighbors.push_back(14);
        neighbors.push_back(15);
    }
    else if(rank == 11){
        neighbors.push_back(4);
        neighbors.push_back(6);
        neighbors.push_back(7);
        neighbors.push_back(8);
        neighbors.push_back(10);
        neighbors.push_back(12);
        neighbors.push_back(14);
        neighbors.push_back(15);
    }
    else if(rank == 12){
        neighbors.push_back(0);
        neighbors.push_back(1);
        neighbors.push_back(3);
        neighbors.push_back(8);
        neighbors.push_back(9);
        neighbors.push_back(11);
        neighbors.push_back(13);
        neighbors.push_back(15);
    }
    else if(rank == 13){
        neighbors.push_back(0);
        neighbors.push_back(1);
        neighbors.push_back(2);
        neighbors.push_back(8);
        neighbors.push_back(9);
        neighbors.push_back(10);
        neighbors.push_back(12);
        neighbors.push_back(14);
    }
    else if(rank == 14){
        neighbors.push_back(1);
        neighbors.push_back(2);
        neighbors.push_back(3);
        neighbors.push_back(9);
        neighbors.push_back(10);
        neighbors.push_back(11);
        neighbors.push_back(13);
        neighbors.push_back(15);
    }
    else if(rank == 15){
        neighbors.push_back(0);
        neighbors.push_back(2);
        neighbors.push_back(3);
        neighbors.push_back(8);
        neighbors.push_back(10);
        neighbors.push_back(11);
        neighbors.push_back(12);
        neighbors.push_back(14);
    }

    for(int i=0; i<8; i++){
        Packet * packet = new Packet();
        receivedData[neighbors[i]] = packet;
        mpiReceiveRequest[neighbors[i]] = world.irecv(neighbors[i], 100, *packet);
    }


    for(int i=1; i<=10; i++){
        if(i%5 == 0){    // Checkpoint time
            for(int j=0; j<8; j++){
                Packet * p = new Packet(neighbors[j], rank, i);
                mpiSendRequest[neighbors[j]] = world.isend(neighbors[j], 100, *p);
                log("Sending: ");
                log(p->toString());
                log("\n");
            }
        }

        for(int j=0; j<8; j++){
            if(mpiReceiveRequest[neighbors[j]].test()){
                Packet * p = receivedData[neighbors[j]];
                log("Received: ");
                log(receivedData[neighbors[j]]->toString());
                log("\n");

                if(p->getData() != 10){
                    Packet * packet = new Packet();
                    receivedData[neighbors[j]] = packet;
                    mpiReceiveRequest[neighbors[j]] = world.irecv(neighbors[j], 100, *packet);
                }
            }
        }
    }

    for(int i=0; i<8; i++){
        stringstream ss;
        ss << "  Wait from: " << neighbors[i] << endl;
        log(ss.str());
        mpiReceiveRequest[neighbors[i]].wait();

        log("Received: ");
        log(receivedData[neighbors[i]]->toString());
        log("\n");
    }

    stringstream ss;
    ss << rank << " is done" << endl;
    log(ss.str());

    return 0;
}

Проблема в том, что он зависает на команде ожидания. Кроме того, некоторые из полученных сообщений содержат бессмысленные данные. Например, выходной файл процесса 7 выглядит следующим образом:

Received: Packet = [Data: 5, Receiver: 7, Sender: 10]
Received: Packet = [Data: 5, Receiver: 7, Sender: 11]
Received: Packet = [Data: 5, Receiver: 7, Sender: 0]
Received: Packet = [Data: 5, Receiver: 7, Sender: 4]
Sending: Packet = [Data: 5, Receiver: 0, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 2, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 3, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 4, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 6, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 8, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 10, Sender: 7]
Sending: Packet = [Data: 5, Receiver: 11, Sender: 7]
  Wait from: 0
Received: Packet = [Data: 537985024, Receiver: 0, Sender: 0]
  Wait from: 2

Я не мог понять, где проблема.

24.10.2015

  • Честно говоря, я не понимаю ваш код. Но сразу становится очевидным, что вы никогда не ждете неблокирующих запросов на отправку, поэтому возможно, что некоторые сообщения никогда не отправляются, и ваш код блокирует ожидание неблокирующих приемов этих никогда не отправленных сообщений. 24.10.2015
  • как вы начинаете дела? Я пробовал с mpirun -np 16 ./test и подобными, но все процессы прерываются. 24.10.2015
  • @HristoIliev Я также пробовал отправить команду вместо isend, но результат тот же. 25.10.2015
  • @sehe Вот как я тоже начал программу. 25.10.2015
  • у меня вообще не работает 25.10.2015
  • Я использую mpich2, а что у вас? 25.10.2015
  • Я использовал мпич. Дай мне посмотреть о версиях. М-м-м. Кажется, он работает, но меня отвлек очень шумный вывод терминала. К сожалению, я не знаю, как это читать. Я мог бы вернуться к этому позже. 25.10.2015

Ответы:


1

Проблема заключалась в вызове команды ожидания для запроса, который был протестирован ранее и пройден. На самом деле я понял, что это также является причиной одного из моих предыдущих вопросов: запросы, которые уже были выполнены

Итак, я изменил свой код, как показано ниже, и теперь он работает:

/* ...
 else if(rank == 15){
    neighbors.push_back(0);
    neighbors.push_back(2);
    neighbors.push_back(3);
    neighbors.push_back(8);
    neighbors.push_back(10);
    neighbors.push_back(11);
    neighbors.push_back(12);
    neighbors.push_back(14);
}
...After assigning neighbors
*/

for(int i=0; i<8; i++){
    Packet * packet = new Packet();
    receivedData[neighbors[i]] = packet;
    mpiReceiveRequest[i] = world.irecv(neighbors[i], 100, *packet);
}

vector<int> completed;
for(int i=1; i<=10; i++){
    if(i%5 == 0){    // Checkpoint time
        for(int j=0; j<8; j++){
            Packet * p = new Packet(neighbors[j], rank, i);
            mpiSendRequest.push_back(world.isend(neighbors[j], 100, *p));
            log("Sending: ");
            log(p->toString());
            log("\n");
        }
    }

    for(int j=0; j<8; j++){
        vector<int>::iterator it = completed.begin();
        bool passed = false;

        while(it != completed.end()){
            if(*it == j){
                passed = true;
                break;
            }
            it++;
        }

        if(!passed){
            if(mpiReceiveRequest[j].test()){
                completed.push_back(j);

                Packet * p = receivedData[neighbors[j]];
                if(p->getData() != 10){
                    Packet * packet = new Packet();
                    receivedData[neighbors[j]] = packet;
                    mpiReceiveRequest[j] = world.irecv(neighbors[j], 100, *packet);
                    completed.pop_back();
                }
            }
        }
    }
}

vector<boost::mpi::request> reqs;
for(int i=0; i<8; i++){
    vector<int>::iterator it = completed.begin();
    bool passed = false;

    while(it != completed.end()){
        if(*it == i){
            passed = true;
            break;
        }
        it++;
    }

    if(!passed){
        mpiReceiveRequest[i].wait();
        reqs.push_back(mpiReceiveRequest[i]);
    }
}

stringstream ss;
ss << rank << " is done" << endl;
log(ss.str());

return 0;
} // End of main

Основное отличие заключается в хранении завершенных запросов в векторе, а не в ожидании их в конце.

27.10.2015
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..