配置文件C执行

Jos*_*osh 5 c profiler clock execution-time

所以,只是为了好玩,出于好奇,我想看看在做奇偶校验,模数或按位比较时执行得更快.

所以,我掀起了以下内容,但我不确定它的表现是否正确,因为差异太小了.我在网上看到,按位应该比模数检查快一个数量级.

它是否有可能被优化掉?我刚刚开始修补程序集,否则我会尝试解析一下可执行文件.

编辑3:这是一个工作测试,非常感谢@phonetagger:

#include <stdio.h>
#include <time.h>
#include <stdint.h>

// to reset the global
static const int SEED = 0x2A;

// 5B iterations, each
static const int64_t LOOPS = 5000000000;

int64_t globalVar;

// gotta call something
int64_t doSomething( int64_t input )
{
  return 1 + input;
}

int main(int argc, char *argv[]) 
{
  globalVar = SEED;

  // mod  
  clock_t startMod = clock();

  for( int64_t i=0; i<LOOPS; ++i )
  {    
    if( ( i % globalVar ) == 0 )
    {
      globalVar = doSomething(globalVar);      
    }    
  }

  clock_t endMod = clock();

  double modTime = (double)(endMod - startMod) / CLOCKS_PER_SEC;

  globalVar = SEED;

  // bit
  clock_t startBit = clock();

  for( int64_t j=0; j<LOOPS; ++j )
  {
    if( ( j & globalVar ) == 0 )
    {
      globalVar = doSomething(globalVar);
    }       
  }

  clock_t endBit = clock();

  double bitTime = (double)(endBit - startBit) / CLOCKS_PER_SEC;

  printf("Mod: %lf\n", modTime);
  printf("Bit: %lf\n", bitTime);  
  printf("Dif: %lf\n", ( modTime > bitTime ? modTime-bitTime : bitTime-modTime ));
}
Run Code Online (Sandbox Code Playgroud)

每个循环的50亿次迭代,以及全局删除编译器优化产生以下结果:

Mod: 93.099101
Bit: 16.701401
Dif: 76.397700
Run Code Online (Sandbox Code Playgroud)

pho*_*ger 2

大多数编译器会将以下两条指令编译为完全相同的机器指令:

if( ( i % 2 ) == 0 )

if( ( i & 1 ) == 0 )
Run Code Online (Sandbox Code Playgroud)

...即使没有打开任何“优化”。原因是您对常量值进行 MOD 和 AND 运算,正如任何编译器编写者都应该知道的那样,%2 操作在功能上等同于 &1 操作。事实上,任何 2 的幂的 MOD 都有等效的 AND 运算。如果您确实想测试差异,则需要使两个操作的右侧都是可变的,并且为了绝对确定编译器的聪明才智不会阻碍您的努力,您需要隐藏变量' 在编译器无法判断其运行时值的地方进行初始化;即您需要将值传递到全局声明(即不是“静态”)测试函数作为参数,在这种情况下,编译器无法追溯到它们的定义并用常量替换变量,因为理论上任何外部调用者可以传递这些参数的任何值。或者,您可以将代码保留在 main() 中并全局定义变量,在这种情况下,编译器无法用常量替换它们,因为它无法确定另一个函数可能已经更改了全局变量的值。

顺便说一句,除法运算也存在同样的问题......除以常数 2 的幂可以用等效的右移 (>>) 运算代替。同样的技巧也适用于乘法 (<<),但乘法的好处较少(或不存在)。真正的除法运算在硬件中只需要很长时间,尽管大多数现代处理器与 15 年前相比已经有了显着的改进,除法运算仍然需要大约 80 个时钟周期,而 >> 运算只需要一个周期。在现代处理器上使用按位技巧你不会看到“数量级”的改进,但大多数编译器仍然会使用这些技巧,因为仍然有一些明显的改进。

编辑:在某些嵌入式处理器上(令人难以置信的是,v8 之前的原始 Sparc 桌面/工作站处理器版本),甚至根本没有除法指令。此类处理器上的所有真正的除法和取模运算都必须完全在软件中执行,这可能是一项极其昂贵的操作。在那种环境下,你肯定会看到一个数量级的差异。