MPI 多线程例子 一个线程管理任务,其他线程完成任务。

很早就想总结自己最近做的,然后一直拖拖到了现在。先总结先MPI多线程所学到的。先给一个简单的多线程实例,这是对图片多重采样的代码,在图片读取采样的时候采用MPI多线程进行编码。

bool DataCreater::creat_temp_data2(QStringList files, QString dst, int level_total, int begin_level, int image_begin)
{

    QStringList file_temp_list;//图片列表
    if (iscreattemp0 == true)
    {
        file_temp_list = updata_src_file_list(dst, begin_level - 1);//the function is used to updata image list
    }
    else
    {
        if (begin_level == 1)
            file_temp_list = files;
        else
            file_temp_list = updata_src_file_list(dst, begin_level - 1);
    }
    QStringList file_temp_list_next_level;
    QString dst_temp = dst;
    QString str2;
    int width = 0, height = 0;
    int processI;
    int numprocs;
    int flag = 1; 
    int flgb = 0;  
    int flag_message[2] = { 0,0 };//interprocess communication signal,fist parameter is process ID,the second parameter is task ID.

    int proc_file_num = 0;
    MPI_Comm_rank(MPI_COMM_WORLD, &processI);//process ID
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);//process number
    int value_proc[200];
    MPI_Status status;// dynamic transmission variable
    for (int level_temp = begin_level; level_temp <= level_total; level_temp++)
    {
        //log file
        std::string block_id_path = dst.toStdString();
        block_id_path = block_id_path + "/log.txt";
        std::ofstream   ofresult(block_id_path.c_str(), std::ios::trunc);
        ofresult << 0 << std::endl;//represent write temp file
        ofresult << level_temp << std::endl;//represent write temp level
        
        const char *path;
        QByteArray text = file_temp_list.at(0).toLocal8Bit();
        path = text.data();
        TIFFSetWarningHandler(0);
        TIFF *tif = TIFFOpen(path, "r");
        if (tif == 0) {
            printf(" open TIFF file %s failed\n", path);
            return false;
        }
        TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
        TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
        TIFFClose(tif);
        int sub_x = int(ceil(width / 2.0));
        int sub_y = int(ceil(height / 2.0));
        uint8 *buffer_slice = new uint8[size_t(width)* size_t(height)];
        uint8 *sub_buffer = new uint8[size_t(sub_x)*size_t(sub_y)];
        uint8 *sub_buffer_odd = new uint8[size_t(sub_x)*sub_y];
        uint8 *sub_buffer_even = new uint8[size_t(sub_x)*sub_y];
        for (int i = 0; i < numprocs; i++)
        {
            value_proc[i] = 0;
        }

      //the process 0 is used to publish task
        if (processI == 0)
        {
            for (int j = 1+ image_begin; j < numprocs+ image_begin; j++)//image_begin is image begin ID,It can be considered as 0
            {
                flag = (j - 1) * 2;
                MPI_Send(&flag, 1, MPI_INT, j- image_begin, 0, MPI_COMM_WORLD);//this will be introduced later in detail
                std::cout << "Temp " << level_temp << " data   processing slice " << BOLDGREEN << flag << RESET << " ---- " << file_temp_list.size() + (numprocs - 1) * 2 - 2 << '\r';
                //printf("Temp %d data   processing slice %d----%d\r",level_temp,flag,file_temp_list.size()+(numprocs-1)*2-2);
                value_proc[j]++;

            }
            //for (int file_index = 9800;file_index<file_temp_list.size()+(numprocs-1)*2;file_index+=2)
            for (int file_index = (numprocs - 1+ image_begin) * 2; file_index < file_temp_list.size() + (numprocs - 1) * 2; file_index += 2)
            {
                MPI_Recv(&flag_message, 2, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
                int flag_procID = flag_message[0];
                flag = file_index;
                if (flag_message[1]== file_temp_list.size() - 1)
                {
                    ofresult << flag_message[1] << std::endl;
                }
                else
                {
                    ofresult << flag_message[1] << std::endl;
                    ofresult << flag_message[1] + 1 << std::endl;
                }
                MPI_Send(&flag, 1, MPI_INT, flag_procID, 0, MPI_COMM_WORLD);
                value_proc[flag_procID]++;
                std::cout << "Temp " << level_temp << " data   processing slice " << BOLDGREEN << flag << RESET << " ---- " << file_temp_list.size() + (numprocs - 1) * 2 - 2 << '\r';
            }

            printf("\n");
            for (int i = 0; i < numprocs; i++)
            {
                //    printf("  process  %d   files  from node %d \n",value_proc[i],i);
            }
        }
        else
        {
            while (1)
            {
                MPI_Recv(&flgb, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);//This is used to establish a connection for the first time,may be can  establish connection direct,this fuction will introduce later
                if (flgb >= file_temp_list.size())
                {
                    break;
                }
                //printf("  is resampling slice %d\n",flgb);
                const char *path;
                QByteArray text = file_temp_list.at(flgb).toLocal8Bit();
                path = text.data();
                load_slice_image_line(path, buffer_slice, width, height);
                slice_resample(buffer_slice, sub_buffer_odd, width, height);
                if (flgb == file_temp_list.size() - 1)
                {
                    for (int index_ddd = 0; index_ddd < size_t(sub_x)*sub_y; index_ddd++)
                    {
                        sub_buffer[index_ddd] = sub_buffer_odd[index_ddd];
                    }
                }
                else
                {
                    const char *path2;
                    QByteArray text2 = file_temp_list.at(flgb + 1).toLocal8Bit();
                    path2 = text2.data();
                    load_slice_image_line(path2, buffer_slice, width, height);

                    slice_resample(buffer_slice, sub_buffer_even, width, height);


                    for (size_t index_ddd = 0; index_ddd < size_t(sub_x)*sub_y; index_ddd++)
                    {
                        sub_buffer[index_ddd] = (sub_buffer_odd[index_ddd] + sub_buffer_even[index_ddd]) / 2;
                    }

                }
                str2 = creat_temp_file_path(dst_temp, level_temp, flgb);
                const QByteArray text2 = str2.toLocal8Bit();
                const char *data = text2.data();
                this->write8bitImage(data, sub_buffer, sub_x, sub_y);
                //this->write_buffer(data,sub_buffer,sub_x,sub_y,1);
                int *message = new int[2];
                message[0] = processI;
                message[1] = flgb;
                MPI_Send(message, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);

            }
        }
        MPI_Barrier(MPI_COMM_WORLD);//wait all process arrive here
        image_begin = 0;
        file_temp_list.clear();
        file_temp_list = updata_src_file_list(dst_temp, level_temp);
        ofresult.close();
    }
    return true;
}

 

下面介绍一下两个主要通信函数

MMPI_Send(
    void* data,//发送的数据,一般是指针
    int count,    //发送指针后面多少个数据
    MPI_Datatype datatype,//数据类型
    int destination,//发送给哪个进程
    int tag,//通信标签
    MPI_Comm communicator)//发送进程的通信子
int MPI_Recv(
        void* msg_buf_p,       接收数据
        int buf_size,          数据个数
        MPI_Datatype buf_type,   数据类型
        int source,                数据来源进程
        int tag,                通信标签
        MPI_Comm communicator,   通信子,与想接收进程这个变量相同
        MPI_Status* status_p    /* OUT */
        );
通过这些可以简单了解MPI的使用,详细还需进一步学习。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值