C 与Windows相比,Linux上的代码速度较慢

C 与Windows相比,Linux上的代码速度较慢,c,windows,linux,optimization,C,Windows,Linux,Optimization,在修改了我的C代码(最初为Windows编写,在VS2008下编译)之后,我在Linux上运行了它。令我惊讶的是,它现在至少比windows版本慢10倍 使用探查器工具,我发现以下函数占用了应用程序中的大部分时间: /* advance by n bits */ void Flush_Buffer(N) int N; { int Incnt; ld->Bfr <<= N; Incnt = ld->Incnt -= N; if (Incnt <= 24)

在修改了我的C代码(最初为Windows编写,在VS2008下编译)之后,我在Linux上运行了它。令我惊讶的是,它现在至少比windows版本慢10倍

使用探查器工具,我发现以下函数占用了应用程序中的大部分时间:

/* 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;
}

}
/*前进n位*/
无效刷新缓冲区(N)
int N;
{
int Incnt;
ld->Bfr=ld->Rdmax-4)
{
做
{
如果(ld->Rdptr>=ld->Rdmax)
下一个_包();
ld->Bfr |=获取字节()Rdbfr+2044)
{
做
{
ld->Bfr |=*ld->Rdptr++=ld->Rdbfr+2048)
填充缓冲区();

ld->Bfr |=*ld->Rdptr++您可以尝试使用计数器对代码中的所有代码路径进行注释。在程序结束时,每个计数器将包含代码路径执行次数的信息。在Windows版本和Linux版本之间逐行比较这些数字可能会发现程序遵循不同的指令t代码路径。根据代码路径的性质,这些差异可能可以解释为什么Linux版本比Windows版本慢

int count[100];

// Call this function at the end of program 
void PrintCounts() {
    int i;
    for(i=0; i<100; i++) printf("%d\n", count[i]);
}

void Flush_Buffer(int N) {
  int Incnt;

  ld->Bfr <<= N;

  Incnt = ld->Incnt -= N;

  if (Incnt <= 24) {
    count[0]++;
    if (System_Stream_Flag && (ld->Rdptr >= ld->Rdmax-4)) {
      count[1]++;
      do {
         count[2]++;
         ...
int计数[100];
//在程序结束时调用此函数
void PrintCounts(){
int i;
对于(i=0;iBfr=ld->Rdmax-4)){
计数[1]++;
做{
计数[2]++;
...

这与其说是一个答案,不如说是一个注释,但它不太适合作为一个评论,所以我希望你不要对我持有异议

术语“评测”有几个相关但不同的含义。在抽象上下文中,它意味着“测量”您的程序,通常是针对某些运行时数据。然而,它与简单地“计时”您的程序不同。计时是评测的一种形式,但还有许多其他形式

例如,假设您不确定某些数据结构应该是
std::set
(树)还是
std::unordered\u set
(哈希表)。没有一个通用的答案,因为这取决于您使用它的目的和处理的数据。在指定要使用的实际数据之前,您完全可能不知道正确的答案。在这种情况下,“分析并决定”这意味着您要制作两个版本的程序,根据实际数据运行它们,并测量运行时间。速度越快的可能就是您想要的

另一方面,GCC有一个称为“profiler”的工具,它的用途非常不同。如果您愿意,它是一个执行路径分析器,它告诉您在哪里(即在哪个函数中)您的程序花费了大部分时间。如果您有一个包含大量子例程的复杂算法,您可能不知道哪些是重要的,这实际上可能取决于您的实际输入。在这种情况下,探查器可以帮助您确定在给定输入数据的情况下调用最多的函数,并且您可以集中精力优化在这些功能上的努力。现在“优化前的配置文件”意味着您需要在开始工作之前确定优先级


也就是说,为了进行比较,您不能使用GCC profiler。相反,在启用了所有优化的两种平台上以及在发布条件下进行编译,然后在同一组输入数据上测量运行时。

除非您至少指定(1)您使用的编译器选项,以及(2),否则此问题毫无意义你是如何衡量花费的时间的。你是如何编译你的代码的(什么编译器,什么选项,(什么警告级别)?不,你问了一个问题,忽略了所有相关信息,然后忽略了提供这些信息的请求,这是走错了方向。你在Linux上使用过优化吗?选项
-O[1 | 2 | 3]
对于
gcc
编译器?@gpuguy:Valgrind让你的应用程序运行速度慢50倍…;而且-O3不是-O3 btwI建议永远不要使用gcc分析器。对于大型函数,开销很小,但对于小型函数,花在函数上的时间主要是分析开销。这意味着,功能完善的程序表现糟糕(并给出非常扭曲的分析结果)使用gcc分析器。当然,由于选择性内联,结果会被扭曲。如果您想测量程序中花费的时间,唯一可行的方法是定期对指令指针和堆栈进行采样,例如oprofile。非常感谢各位,我正在按照您的评论,我们会回复您的