Pipeline模式实现Hamilton图判定的并行算法

0) 工程文件

QT -= gui

CONFIG += c++11 console
CONFIG -= app_bundle

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

DEFINES += WIN32
DEFINES += _WINDOWS
DEFINES += NDEBUG
DEFINES += BLOCKING_MODE
DEFINES += NO_DEFAULT_MAPPING
DEFINES += _WIN64
DEFINES += _AMD64_
DEFINES += NOMINMAX
DEFINES += USE_CMAKE_CONFIG
DEFINES += _CRT_SECURE_NO_WARNINGS
DEFINES += CMAKE_INTDIR="Release"

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
        main.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

INCLUDEPATH += $$PWD/../../fastflow

1)源码

#include <QCoreApplication>
#include <ff/pipeline.hpp>

#include <iostream>
#include <vector>
using namespace std;

using namespace ff;

typedef vector<int> PATH;
typedef vector<PATH> PATHS;
typedef vector<vector<bool> > GRAPH_ADJ;
typedef vector<vector<PATH> > SINGLE_PATH_ARRAY;
typedef vector<vector<PATHS> > MULTI_PATHS_ARRAY;

struct Task
{
    MULTI_PATHS_ARRAY mpa;
};

typedef Task myTask;
static myTask simpleGraph;

MULTI_PATHS_ARRAY pathArrayMultiply(const MULTI_PATHS_ARRAY m_multiPathsArray, const MULTI_PATHS_ARRAY pathArrayG, MULTI_PATHS_ARRAY& retPathsArr)
{
    //initialize the retPathArray
    retPathsArr.resize(pathArrayG.size());
    for (int i=0; i < pathArrayG.size(); ++i) {
        retPathsArr[i].resize(pathArrayG.size());
    }

    for (int i = 0; i < pathArrayG.size(); ++i){
        for(int j= 0; j< pathArrayG.size(); ++j)
        {
            PATHS retPaths;
            for (int k=0; k < pathArrayG.size(); ++k) {
                //if one of path is [0], the result is 0
                if(((m_multiPathsArray[i][k].size() == 1) && (m_multiPathsArray[i][k][0].size() == 1))
                        || ((pathArrayG[k][j].size() == 1) && (pathArrayG[k][j][0].size() == 1)))
                {
                    continue;
                }

                for (int x = 0; x < m_multiPathsArray[i][k].size(); ++x){
                    for(int y= 0; y< pathArrayG[k][j].size(); ++y)
                    {
                        PATH tempPath;
                        PATH op1path = m_multiPathsArray[i][k][x];
                        PATH op2path = pathArrayG[k][j][y];
                        bool bFlagCross = false;
                        int nCrossCount = 0;

                        if(op1path[op1path.size() -1] == op2path[0])
                        {
                            for (int m = 0; m < op1path.size() - 1; ++m) {
                                for (int n=0; n < op2path.size(); ++n) {
                                    if (op1path[m] == op2path[n]){
                                        bFlagCross = true;
                                        nCrossCount ++;
                                    }
                                }
                            }

                            if((op1path[0] == op2path[op2path.size() -1]) && (nCrossCount == 1))
                            {
                                if(m_multiPathsArray.size() == op1path.size() + op2path.size()  - 2)
                                    bFlagCross = false;
                            }

                            if( !bFlagCross ){
                                tempPath = op1path;
                                for(int n=1; n< op2path.size(); ++n)
                                {
                                    tempPath.push_back(op2path[n]);
                                }
                            }
                        }

                        retPaths.push_back(tempPath);

                    }
                }
            }

            for (const auto& path: retPaths) {
                if (path.size() !=0){
                    retPathsArr[i][j].push_back(path);
                }
            }

            //if the path is null, fill it with zero
            if(retPathsArr[i][j].size() == 0)
            {
                retPathsArr[i][j].resize(1);
                retPathsArr[i][j][0].push_back(0);
            }
        }
    }

    return retPathsArr;
}

bool isZero(MULTI_PATHS_ARRAY m_multiPathsArray)
{
    bool bRet = true;
    for (int i = 0; i < m_multiPathsArray.size(); ++i){
        for(int j= 0; j< m_multiPathsArray.size(); ++j)
        {
            if (!((m_multiPathsArray[i][j].size() == 1) && (m_multiPathsArray[i][j][0][0] == 0)
                    || (m_multiPathsArray[i][j].size() ==0)))

                return false;
        }
    }
    return bRet;
}

struct firstStage: ff_node_t<myTask>{
    myTask *svc(myTask*){
        std::cout << "hello, I am stage" << get_my_id() + 1 << std::endl;

        vector<vector<bool>> graph = {
                {0, 1, 0, 1, 0},
                {1, 0, 1, 1, 1},
                {0, 1, 0, 0, 1},
                {1, 1, 0, 0, 1},
                {0, 1, 1, 1, 0}
            };

        SINGLE_PATH_ARRAY singlePathArray;
        singlePathArray.resize(graph.size());
        for (int i = 0; i < graph.size(); ++i){
            singlePathArray[i].resize(graph.size());
        }

        for (int i = 0; i < graph.size(); ++i){
            for(int j= 0; j< graph.size(); ++j)
            {
                if(graph[i][j] == 0)
                {
                    singlePathArray[i][j].push_back(0);
                } else {
                    singlePathArray[i][j].push_back(i);
                    singlePathArray[i][j].push_back(j);
                }

            }
        }

        MULTI_PATHS_ARRAY& pathsArray = simpleGraph.mpa;

        pathsArray.resize(singlePathArray.size());
        for (int i = 0; i < singlePathArray.size(); ++i){
            pathsArray[i].resize(singlePathArray.size());
        }

        for (int i = 0; i < singlePathArray.size(); ++i){
            for(int j= 0; j< singlePathArray.size(); ++j)
            {
                pathsArray[i][j].resize(1);
                pathsArray[i][j][0]=singlePathArray[i][j];
            }
        }

        ff_send_out(new myTask(simpleGraph));
        return EOS;
    }
};

struct secondStage: ff_node_t<myTask>{
    myTask *svc(myTask* t){
        std::cout << "hello, I am stage" << get_my_id() + 1 << std::endl;
        myTask* productTask = new myTask();
        pathArrayMultiply(t->mpa, simpleGraph.mpa, productTask->mpa);

        if (t != NULL){
            delete  t;
            t = NULL;
        }
        return productTask;
    }
};

struct thirdStage: ff_node_t<myTask>{
    myTask *svc(myTask* t){
        std::cout << "hello, I am stage" << get_my_id() + 1 << std::endl;
        myTask* productTask = new myTask();
        pathArrayMultiply(t->mpa, simpleGraph.mpa, productTask->mpa);

        if (t != NULL){
            delete  t;
            t = NULL;
        }

        return productTask;
    }
};

struct forthStage: ff_node_t<myTask>{
    myTask *svc(myTask* t){
        std::cout << "hello, I am stage" << get_my_id() + 1 << std::endl;
        myTask* productTask = new myTask();
        pathArrayMultiply(t->mpa, simpleGraph.mpa, productTask->mpa);

        if (t != NULL){
            delete  t;
            t = NULL;
        }
        return productTask;
    }
};

struct fifthStage: ff_node_t<myTask>{
    myTask *svc(myTask* task){
        std::cout << "hello, I am stage" << get_my_id() + 1 << std::endl;
        myTask* productTask = new myTask();
        pathArrayMultiply(task->mpa, simpleGraph.mpa, productTask->mpa);

        if (task != NULL){
            delete  task;
            task = NULL;
        }

        MULTI_PATHS_ARRAY pathsArray = productTask->mpa;

        if (isZero(pathsArray)){
            error("Not a Hamilton Graph");
        }
        else {

            if(pathsArray.size() == 0)
            {
                cout << "Paths Array vector is null\n";
                return GO_ON;
            }

            std::cout << "This is a Hamilton Graph. Path is shown in following Array Diagonal" << std::endl;

            for (auto& line : pathsArray) {
                for (const auto& column : line) {
                    cout << "[";
                    for (const auto& path: column) {
                        if (path.size() == 1){
                            cout << "[0]";
                            continue;
                        }
                        cout << "[";
                        for (size_t i = 0; i < path.size(); ++i) {
                            cout << path[i];
                            if (i != path.size() - 1)
                                cout << "->";
                        }
                        cout << "]";
                    }
                    cout << "]";
                }
                cout << endl;
            }

        }

        std::cout << std::endl;
        if (productTask != NULL){
            delete  productTask;
            productTask = NULL;
        }
        return GO_ON;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    firstStage _1;
    secondStage _2;
    thirdStage _3;
    forthStage _4;
    fifthStage _5;
    ff_Pipe<> pipe(_1, _2, _3, _4, _5);
    if(pipe.run_and_wait_end() <0) {
        error("running pipe");
    }

    return a.exec();
}

2)运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本资源设置1个资源分,您可以下载作为捐献。 如果您有Git,还可以从http://www.goldenhawking.org:3000/goldenhawking/zoom.pipeline直接签出最新版本 (上一个版本“一种可伸缩的全异步C/S架构服务器实现”是有问题的,现在已经完成更改)。 服务由以下几个模块组成. 1、 网络传输模块。负责管理用于监听、传输的套接字,并控制数据流在不同线程中流动。数据收发由一定规模的线程池负责,实现方法完全得益于Qt的线程事件循环。被绑定到某个Qthread上的Qobject对象,其信号-槽事件循环由该线程负责。这样,便可方便的指定某个套接字对象使用的线程。同样,受惠于Qt的良好封装,直接支持Tcp套接字及SSL套接字,且在运行时可动态调整。(注:编译这个模块需要Qt的SSL支持,即在 configure 时加入 -openssl 选项) 2、 任务流水线模块。负责数据的处理。在计算密集型的应用中,数据处理负荷较重,需要和网络传输划分开。基于普通线程池的处理模式,也存在队列阻塞的问题——若干个客户端请求的耗时操作,阻塞了其他客户端的响应,哪怕其他客户端的请求很短时间就能处理完毕,也必须排队等待。采用流水线线程池避免了这个问题。每个客户端把需要做的操作进行粒度化,在一个环形的队列中,线程池对单个客户端,每次仅处理一个粒度单位的任务。单个粒度单位完成后,该客户端的剩余任务便被重新插入到队列尾部。这个机制保证了客户端的整体延迟较小。 3、 服务集群管理模块。该模块使用了网络传输模块、任务流水线模块的功能,实现了跨进程的服务器ßà服务器链路。在高速局域网中,连接是快速、稳定的。因此,该模块被设计成一种星型无中心网络。任意新增服务器节点选择现有服务器集群中的任意一个节点,接入后,通过广播自动与其他服务器节点建立点对点连接。本模块只是提供一个服务器到服务器的通信隧道,不负责具体通信内容的解译。对传输内容的控制,由具体应用决定。 4、 数据库管理模块。该模块基于Qt的插件式数据库封装QtSql。数据库被作为资源管理,支持在多线程的条件下,使用数据库资源。 5、 框架界面。尽管常见的服务运行时表现为一个后台进程,但为了更好的演示服务器的功能,避免繁琐的配置,还是需要一个形界面来显示状态、设置参数。本范例中,界面负责轮训服务器的各个状态,并设置参数。设置好的参数被存储在一个ini文件中,并在服务开启时加载。 6、应用专有部分模块。上述1-4共四个主要模块均是通用的。他们互相之间没有形成联系,仅仅是作为一种资源存在于程序的运行时(Runtime)之中。应用专有部分模块根据具体任务需求,灵活的使用上述资源,以实现功能。在范例代码中,实现了一种点对点的转发机制。演示者虚拟出一些工业设备,以及一些操作员使用的客户端软件。设备与客户端软件在成功认证并登录后,需要交换数据。改变这个模块的代码,即可实现自己的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值