【发布时间】:2016-12-26 18:45:50
【问题描述】:
我正在尝试分析一些 C 代码,但在 GProf 输出中没有显示最直观昂贵的函数之一。
int main() {
initialise...
haloSwap();
for(...) {
functions...
propagate();
functions...
}
}
void propagate() {
for (x)
for (y)
for (z)
grid[xNew][yNew][zNew] = grid[x][y][z];
haloSwap();
}
void haloSwap() {
// Horizontal swap
create buffers...
MPI_Sendrecv(buffers);
recreate grid from buffers...
// Vertical swap
create buffers...
MPI_Sendrecv(buffers);
recreate grid from buffers...
}
希望伪代码能够在某种程度上解释设置。 haloSwap() 涉及线程之间的大量通信,我觉得这是算法中昂贵的部分。它在初始化期间调用,然后在算法循环期间重复调用。
GProf 仅显示对 haloSwap 的 1 次调用(在初始化期间),尽管我知道它在 propagate() 内部被调用了 1000 多次。
propagate() 显示为代码中最昂贵的部分,但我想知道它是 xyz 循环还是 MPI 通信。
有谁知道为什么从propagate 对haloSwap 的调用在调用次数和函数中花费的时间似乎都被忽略了?
haloSwap 在另一个 .c 文件中定义,这可能是一个因素?
如果我在调用propagate 之后将haloSwap 的调用移动到主循环(而不是在其中),GProf 仍然只显示 1 次调用。
【问题讨论】:
-
您可能正在编译优化,
propagate()最终被内联。告诉你的编译器不要内联函数。例如,对于 GCC,选项是-fno-inline。 -
添加到@Hristo_Iliev 评论。 mpicc(来自 MPICH)包装器使用 -O2 优化,其中包括 -finline-small-functions 标志。如果您希望从任何优化中排除某些函数,请使用函数的 gcc 属性,例如 void haloSwap() __attribute__(optimize("-O0"))
-
如果您使用的是 MPI,那么它正在执行 I/O,而众所周知 gprof 对此视而不见,因为采样在 I/O 期间暂停。您可能将 99% 的时间花在 I/O 上,但 gprof 不会显示出来。任何自称为“CPU 分析器”的东西也是如此。
-
@MikeDunlavey 我想穷人的方法是检查实际经过的时间与 gprof 报告的 CPU 时间?
-
@KallumBurgin:这将显示问题。有些人使用this technique,它可以实时工作,而不仅仅是CPU时间。它的时间精度较低,但定位问题的精度更高。