我正在研究一个将数组乘以矩阵的小应用程序。它没有任何问题。我正在努力衡量应用程序的执行时间。我可以找到每个进程的执行时间(开始和结束),但我需要全局时间。
这是我的代码:
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
答案 0 :(得分:33)
在大多数情况下,通常只需跟踪主节点上的开始和结束时间 ,并仅在主节点上导出全局运行时间。
值得注意的一点是,您必须在收集开始时间之前放置屏障(以确保所有节点都已准备好继续),并在结束时间之前 (以确保完成所有节点。)
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
)。
答案 1 :(得分:10)
MPI_Init()
和MPI_Finalize()
不标记并行执行的开始和结束,仅标记允许MPI调用的开始和结束。在MPI中,所有进程从头到尾并行运行,并且不共享任何全局数据。
您可以使用MPI_Reduce()
查找流程的最短开始时间和最长结束时间。
答案 2 :(得分:2)
您可以像此代码段一样使用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_Reduce(
void* send_data,
void* recv_data,
int count,
MPI_Datatype datatype,
MPI_Op op,
int root,
MPI_Comm communicator)