【问题标题】:MPI global execution timeMPI 全局执行时间
【发布时间】:2011-07-14 23:59:37
【问题描述】:

我正在开发一个将数组与矩阵相乘的小应用程序。它可以正常工作。我正在寻找测量应用程序的执行时间。我可以找到每个进程的单独执行时间(它的开始和结束),但我需要全局时间。

这是我的代码:

int main(int argc, char **argv){
    int rang, procesus;
    MPI_Status statut;
    double start, end, max_end = 0, min_start = 10000;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rang);
    MPI_Comm_size(MPI_COMM_WORLD, &procesus);
    MPI_Barrier(MPI_COMM_WORLD);

    start = MPI_Wtime();
    printf("Starting time of process n. %d %f\n",rang, start);
    if(rang==0){
        //Master work
    }else{
        //slaves work
    }
    MPI_Barrier(MPI_COMM_WORLD);
    end = MPI_Wtime();
    printf("Ending time of process n.%d %f\n\n\n",rang, end);

    MPI_Finalize();
//Out of the Parallelized task

    if(min_start > start){
        min_start = start;
        printf("New minumum starting time %f\n", min_start);
    }

    if(max_end < end){
        max_end = end;
        printf("New maximum ending time %f\n", max_end);
    }

    if(rang == 0){
        printf("Start %f\n", min_start);
        printf("End %f\n", max_end);
    }
    return 0;
}

我使用变量 min_start 和 max_end 作为“全局”变量来尝试捕获所有进程的最大和最小温度,但我总是得到最后一个要执行的进程的开始和结束时间,结束时间还可以,但开始时间错误,因为最后一个进程不是第一个开始的。我究竟做错了什么?我可以在 MPI 中为所有进程使用真正的全局变量吗?如果可以的话?

这就是我的输出

Starting time of process n.2. 0.101562
Ending time of process n.2. 0.105469
New minumum starting time 0.101562
New maximum ending time 0.105469

Starting time of process n.3. 0.058594
Ending time of process n.3. 0.062500
New minumum starting time 0.058594
New maximum ending time 0.062500

Starting time of process n. 4. 0.007812
Ending time of process n. 4. 0.011719
New minumum starting time 0.007812
New maximum ending time 0.011719

Starting time of process n.1. 0.148438
Ending time of process n.1. 0.152344
New minumum starting time 0.148438
New maximum ending time 0.152344

Starting time of process n.0. 0.207031 
Ending time of process n.0. 0.210938
New minumum starting time 0.207031
New maximum ending time 0.210938

Start 0.207031
End 0.210938

【问题讨论】:

    标签: runtime mpi


    【解决方案1】:

    在大多数情况下,只需跟踪主节点上的开始和结束时间并仅在主节点上导出全局运行时间就足够了。

    值得注意的是,您必须在收集开始时间之前放置一个障碍(以确保所有节点都准备好​​继续),并且在结束时间之前 (以确保所有节点都已完成)。

    double start, end;
    
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    
    MPI_Barrier(MPI_COMM_WORLD); /* IMPORTANT */
    start = MPI_Wtime();
    
    /* ... do work ... */
    
    MPI_Barrier(MPI_COMM_WORLD); /* IMPORTANT */
    end = MPI_Wtime();
    
    MPI_Finalize();
    
    if (rank == 0) { /* use time on master node */
        printf("Runtime = %f\n", end-start);
    }
    

    根据每个节点从MPI_Barrier 调用返回的速度,在所有节点上执行相同操作将得到几乎相同的结果,但偏差很小。与大多数实际运行相比,这通常是一个非常小的值,可以打折。

    尝试使用来自不同节点的开始/结束时间得出时间是不值得的,如果MPI_Wtime 不使用global synchronised clock,可能会给出错误的答案。请注意,某些 MPI 实现不支持同步 Wtime(请查看 MPI_WTIME_IS_GLOBAL)。

    【讨论】:

    • 嗨。感谢您的回答。实际上,由于我的输出,我仍然感到困惑。进程 0 是我的主进程,但它在其他进程之后启动(假设其他进程中的工作需要从主进程发送一些信息)。我可以很容易地找到谁是第一个开始的进程(我的输出中的#4),但我不知道如何在执行完成后保存这个值并在最后一个完成的进程中获取它。
    • @jomaora。在 MPI 中,您的变量不会跨进程共享。每个进程都会看到自己的startendmin_startmax_end 版本,这就是为什么在你的代码中,每个进程都会说min_start 是它们的开始时间,max_end 是它们的结束时间时间。最后一个打印块总是 p0 打印出他自己的开始和结束时间。如果您想找出所有处理器的最小值/最大值,请按照@suszterpatt 提到的方法使用MPI_Reduce
    • Shawn.. 你救了我的命!
    • 嘿,关于 MPI_Barrier,你知道它为什么会这样吗stackoverflow.com/questions/29757817/…
    • 是否打算使用%d 进行打印?它会生成警告。是因为我们想保持结果简单吗?或者,在实际实验中计算秒数以外的其他东西可能没有关系?
    【解决方案2】:

    MPI_Init()MPI_Finalize() 不标记并行执行的开始和结束,只标记允许 MPI 调用的开始和结束。在 MPI 中,您的所有进程从头到尾并行运行,并且不共享任何全局数据。

    您可以使用MPI_Reduce() 查找进程的最小开始时间和最大结束时间。

    【讨论】:

    • 如果时钟不同步,使用不同节点的开始/结束时间计算运行时间可能会产生无效结果。
    • 嗨...是的...为了解决这个问题,我添加了 MPI_Reduce 来查找所有进程的开始和结束时间的最大值和最小值...谢谢您的提示.. . :)
    • @ShawnChin,你是什么意思?如果时钟不同步,则开始和结束时间将(可能完全)不同,但它们的区别应该是当前进程的经过时间,所以要么我说错了,要么你的意思是别的。你可以解释吗?提前谢谢你。
    【解决方案3】:

    你可以像这段代码 sn-p 一样使用 MPI_REDUCE

     mytime = MPI_Wtime(); /*get time just before work section */
    
       work(myrank); /*need to create */
    
       MPI_Barrier(MPI_COMM_WORLD);
    
       mytime = MPI_Wtime() - mytime; /*get time just after work section*/
    
    
    
    /*compute max, min, and average timing statistics*/
    
    MPI_Reduce(&mytime, &maxtime, 1, MPI_DOUBLE,MPI_MAX, 0, MPI_COMM_WORLD);
    
    MPI_Reduce(&mytime, &mintime, 1, MPI_DOUBLE, MPI_MIN, 0,MPI_COMM_WORLD);
    
    MPI_Reduce(&mytime, &avgtime, 1, MPI_DOUBLE, MPI_SUM, 0,MPI_COMM_WORLD);
    
    if (myrank == 0) 
    
       {
    
      avgtime /= numprocs;
    
      printf("Min: %lf Max: %lf Avg: %lf\n", mintime, maxtime,avgtime);
       }
    
    MPI_Finalize ();
    

    MPI_Reduce 获取每个进程的输入元素数组,并将输出元素数组返回给根进程。输出元素包含缩减后的结果。

    • MPI_MAX - 返回最大元素。
    • MPI_MIN - 返回最小元素。
    • MPI_SUM - 对元素求和。
    • MPI_PROD - 将所有元素相乘。
    • MPI_LAND - 跨元素执行逻辑和。
    • MPI_LOR - 跨元素执行逻辑或。
    • MPI_BAND - 逐位和跨元素位执行。
    • MPI_BOR - 按位或跨元素的位执行。
    • MPI_MAXLOC - 返回最大值和拥有它的进程的等级。
    • MPI_MINLOC - 返回最小值和拥有它的进程的等级。
    MPI_Reduce(
        void* send_data,
        void* recv_data,
        int count,
        MPI_Datatype datatype,
        MPI_Op op,
        int root,
        MPI_Comm communicator)
    

    【讨论】:

      猜你喜欢
      • 2011-11-30
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多