修改我的 C 代码后,(最初为 Windows 编写并在 VS 2008 下编译),我在 Linux 上运行它。令我惊讶的是,它现在至少比 Windows 版本慢 10 倍。
使用 Profiler 工具,我发现以下函数消耗了应用程序中花费的大部分时间:
/* advance by n bits */
void Flush_Buffer(N)
int N;
{
int Incnt;
ld->Bfr <<= N;
Incnt = ld->Incnt -= N;
if (Incnt <= 24)
{
if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4))
{
do
{
if (ld->Rdptr >= ld->Rdmax)
Next_Packet();
ld->Bfr |= Get_Byte() << (24 - Incnt);
Incnt += 8;
}
while (Incnt <= 24);
}
else if (ld->Rdptr < ld->Rdbfr+2044)
{
do
{
ld->Bfr |= *ld->Rdptr++ << (24 - Incnt);
Incnt += 8;
}
while (Incnt <= 24);
}
else
{
do
{
if (ld->Rdptr >= ld->Rdbfr+2048)
Fill_Buffer();
ld->Bfr |= *ld->Rdptr++ << (24 - Incnt);
Incnt += 8;
}
while (Incnt <= 24);
}
ld->Incnt = Incnt;
}
}
此函数在 Windows 上花费的时间可以忽略不计。在 Linux 上,它花费了将近 14 秒。我在这里犯了什么错?
这里没有系统调用,所以这段代码应该独立于操作系统特定的调用,因此应该在同一时间运行。
(我的猜测:这个函数被多次调用,所以分析器可能也在累积所有调用的时间。在这种情况下,我认为问题之一可能是函数没有得到它的输入与 Windows 情况相比参数更快。)
我在这里犯了什么错?任何猜测?
Rgrds,
H
最佳答案
这与其说是一个答案,不如说是一个注释,但它不太适合作为评论,所以我希望你不要因为这个而反对我。
术语“剖析”有几个相关但不同的含义。在抽象上下文中,它意味着“测量”您的程序,通常是相对于某些运行时数据。但是,这与简单地“计时”您的程序不同。时间是分析的一种形式,但还有许多其他形式。
例如,假设您不确定某些数据结构应该是 std::set
(树)还是 std::unordered_set
(哈希表).没有通用的答案,因为这取决于您使用它的目的以及您正在处理的数据。您完全有可能无法知道正确的答案,直到您指定了您将要使用的真实数据。在那种情况下,“概要分析和决定”意味着您制作程序的两个版本,针对您的真实数据运行它们,并测量运行时间。更快的可能是您想要的。
另一方面,GCC 有一个名为“profiler”的工具,它的用途非常不同。它是一个执行路径分析器,如果你愿意的话,它会告诉你你的程序在哪里(即在哪个函数中)花费了大部分时间。如果你有一个包含很多子程序的复杂算法,你可能不知道哪些是重要的,而且这实际上可能取决于你在现实世界中的输入。在这种情况下,探查器可以帮助您确定哪些函数被调用的次数最多给定您的输入数据,并且您可以将优化工作集中在这些函数上。现在,“优化前的分析”意味着您需要在开始工作之前确定优先级。
就是说,对于您想要的比较,您不能使用 GCC 分析器。相反,在启用所有优化并在发布条件下在两个平台上编译,然后测量同一组输入数据的运行时间。
关于与 Windows 相比,Linux 上的代码速度较慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9546487/