在 MPI 中使用循环

Using Loops in MPI

本文关键字:循环 MPI      更新时间:2023-10-16

我正在尝试通过反转和在 C 上使用 MPI 编码来对大型数组进行排序。

基本上,我的程序将数组拆分为工作线程的部分,每个工作线程找到自己的递增和递减条带,并将条带发送回根目录。Root 通过查找和使用这些条带的最大和最小元素来进行一些反转。当没有剩余断点时,程序结束,这意味着数组已排序。

这是一个很长的代码,所以我简化了我的问题:

int *ARRAY;
int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs, flag = 1;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);
    if(p_id == 0) { 
        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY
        while(hasBreakPoints(ARRAY, N_DATA)) {
            for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS
            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS
            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }
        flag = 0;
        // PRINT SORTED ARRAY
    }
    else {
        while(flag == 1) {
            // RECEIVE PORTION FROM ROOT
            // FIND MY OWN STRIPS
            // SEND MY OWN STRIPS TO ROOT
        }
    }
    MPI_Finalize();
    return 0;
}

如您所见,我需要使用 while 循环来运行程序,直到没有断点。我知道MPI_Send命令的数量必须等于MPI_Receive命令的数量。因此,我只是创建了一个标志来运行ROOTWORKERS相同的时间。

通过使用这种懒惰的方法,程序可以正常工作,但永远不会结束,也不会进入MPI_Finalize。是否有任何关于这种或更有效的使用方式的修复?感谢您的帮助。

你的flag变量是每个进程的局部变量,你必须找到一种方法,当它发生变化时,将其值从进程#0转移到其他进程。

实际上,您可以通过例如使用消息标签来解决此问题。您的工作进程可以使用MPI_ANY_TAG从根接收,并决定下一步要做什么,即发回数据或刚刚完成,具体取决于收到的实际标记值。这可能看起来像这样(未测试):

int *ARRAY;
int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs, flag = 1;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);
    const int COMPUTE=1, STOP=2;
    if(p_id == 0) { 
        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY
        while(hasBreakPoints(ARRAY, N_DATA)) {
            for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS using tag COMPUTE
                MPI_Send(......, COMPUTE, ...);
            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS
            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }
        // send the STOP message using tag STOP
        for(i=1;i<n_procs; i++)
             MPI_Send(....,  STOP, ...);
        // PRINT SORTED ARRAY
    }
    else {
        while(flag == 1) {
            // RECEIVE PORTION FROM ROOT using MPI_ANY_TAG
            MPI_Recv(..., MPI_ANY_TAG, ..., &status);
            if ( status.MPI_TAG == COMPUTE ) {
                // FIND MY OWN STRIPS
                // SEND MY OWN STRIPS TO ROOT
            }
            else
                flag = 0;
        }
    }
    MPI_Finalize();
    return 0;
}

正如Gilles指出的那样,flag不能用于我的程序。我通过检查数组是否在ROOTWORKER部分都排序来解决问题。为此,我必须将ARRAY传递给ROOT的工人。而且,可以选择地将ARRAY保留在工人部分中作为LOCAL.

int *ARRAY;
int main(int argc, char *argv[]) 
{ 
    int p_id, n_procs;
    MPI_Init(&argc, &argv);
    MPI_Status status;
    MPI_Comm_rank(MPI_COMM_WORLD, &p_id);
    MPI_Comm_size(MPI_COMM_WORLD, &n_procs);
    if(p_id == 0) { 
        ARRAY = createRandomArray(N_DATA);
        // PRINT UNSORTED ARRAY
        while(hasBreakPoints(ARRAY, N_DATA)) {
                for(i=1;i<n_procs; i++) 
                // SEND WHOLE ARRAY TO ALL WORKERS
                for(i=1;i<n_procs; i++) 
                // SEND PORTIONS TO WORKERS
            for(i=1;i<n_procs; i++)
                // RECEIVE EACH STRIP FROM WORKERS
            // FIND MAX AND MIN OF STRIPS
            // MAKE REVERSALS ON "ARRAY"    
        }          
        // PRINT SORTED ARRAY
    }
    else {
        int *LOCAL;
        // RECEIVE ARRAY TO LOCAL
        while(hasBreakPoints(LOCAL, N_DATA) {
            // RECEIVE PORTION FROM ROOT
            // FIND MY OWN STRIPS
            // SEND MY OWN STRIPS TO ROOT
        }
    }
    MPI_Finalize();
    return 0;
}

虽然我不明白怎么做,但这解决了我的问题。我仍然愿意听取您的意见。谢谢。