【问题标题】:Execution time for C++ Functions contradictC++ 函数的执行时间相矛盾
【发布时间】:2014-09-16 15:57:59
【问题描述】:

我有一个调用两个用户定义函数的主函数。这两个函数以不同的方式(在一个函数中使用 if else 而在另一个函数中不使用 if else)执行相同的任务(在此简单选择中,选择因子为 50%)。我测量了这两个函数的执行时间。

    int main()
    {
     clock_t t;
     period=clock();
     func1();
     period=clock()-period;
     print period

     period=clock();
     func2();
     period=clock()-period;
     print period
   }

   void func1()
   {
    int A[100000],B[100000],in=0;
    for (i=0;i<100000;i++)
    {
      A[i]=i;
    }
    for (i=0;i<100000;i++)
    {
      if(A[i]==3)
      B[in++]=i;
    }
   }

Func2 与此类似,只是我将 if 替换为非分支语句。

当我执行程序时,首先调用哪个函数需要更多时间。在上述情况下, func1 需要更多时间。如果我先调用 func2 然后调用 func1 ,那么 func2 需要更多时间。我真的不明白这背后的逻辑。

谁能解释一下。

【问题讨论】:

  • 可能是因为第一个实现将输入集带入了缓存。不过,如果没有看到实际来源就很难说。
  • 好的 2 分钟...我将使用源代码编辑问题
  • @vinodc,您的代码不可编译。如果您按照stackoverflow.com/help/mcve 的指南发布代码,您可能会得到一些积极的反馈。
  • 您的测试实际表明,人们认为对性能有影响的事情通常不会,而确实会产生影响的事情是出乎意料的。至少你做了一个测试,很多人“只知道”什么是慢的,为什么并“修复”它

标签: c++


【解决方案1】:

如果Func2Func1 除了第二个循环中的分支相同,我的猜测是对于调用的第一个函数,操作系统必须为堆栈提交页面,而第二个函数可以使用已经提交的页面。

操作系统倾向于仅按需提交内存,以便更多程序可以放入物理内存中。对于一个新线程,Windows 提交(实际上是用物理内存页支持虚拟内存地址)可执行文件头中指定的堆栈数量。然后,仅当进程接触该页面时,它才会提交更多的堆栈页面。它会继续这样做,直到达到指定的保留大小,之后它将生成堆栈溢出异常。 Microsoft 的link.exe 使用的默认设置是为每个堆栈保留 1MB 的虚拟地址空间,并提交单个页面 (4kB)。

当进程确实接触到页面时,处理器会尝试在 Translation Look-aside Buffer 中查找虚拟地址。它不会被找到 - TLB 'miss' - 所以它会尝试在进程的页表中查找它。页表将包含无效条目,因此会引发缺页异常。

操作系统的页错误处理程序查看页表项并确定它属于线程堆栈,因此它找到一个空的内存页,修改其页框数据库以标记该页现在属于该进程,修改页表以指向新页,然后解除异常。处理器使用出错的指令重新开始执行。

处理器异常处理。一堆上下文信息被推送到堆栈上,因此处理器知道返回到哪里,管道停止,TLB 可能不再有操作系统代码的位置,指令和数据缓存可能没有操作系统代码或其中的数据。

假设int 在您的编译器上是 32 位的,那么第一个数组中有 400,000 个字节,第二个数组中有另外 400,000 个字节。第一个循环将生成(可能)98 个页面错误来创建第一个数组,然后第二个循环可能会生成另一个错误以将 B[0] 设置为 3。

它还取决于您的编译器、操作系统和编译器选项。对于像这样在堆栈上声明的大型数组,一些编译器会在函数的开头生成一个“堆栈探测”,以确保堆栈正确提交。 Windows 要求进程以正确的顺序逐页提交其堆栈,因此 Microsoft 的编译器在函数的开头插入对 _chkstk 函数的调用。这故意从每个堆栈页面依次读取,以便操作系统提交页面。这在KB 100775 中有记录。

Linux reportedly just commits stack pages on-demand,并且不要求程序以正确的顺序提交页面。

【讨论】:

    猜你喜欢
    • 2018-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多