【问题标题】:Why the cos function in math.h faster than x86 fcos instruction为什么 math.h 中的 cos 函数比 x86 fcos 指令快
【发布时间】:2019-04-13 13:00:44
【问题描述】:

math.h 中的 cos() 比 x86 asm fcos 运行得更快。

以下代码是 x86 fcos 和 math.h 中 cos() 的比较。

在这段代码中,1000000 次 asm fcos 花费 150ms; 1000000 次 cos() 调用只需 80 毫秒。

fcos 在 x86 中是如何实现的? 为什么 fcos 比 cos() 慢很多?

我的环境是intel i7-6820HQ + win10 + visual studio 2017。

#include "string"
#include "iostream"
#include<time.h>
#include "math.h"

int main()
{
  int i;
  const int i_max = 1000000;

  float c = 10000;
  float *d = &c;

  float start_value = 8.333333f;
  float* pstart_value = &start_value;
  clock_t a, b;
  a = clock();

  __asm {
    mov edx, pstart_value; 

    fld [edx];
  }

  for (i = 0; i < i_max; i++) {
    __asm {
        fcos;
    }
  }


  b = clock();
  printf("asm time = %u", b - a);

  a = clock();
  double y;
  for (i = 0; i < i_max; i++) {
    start_value = cos(start_value);
  }

  b = clock();
  printf("math time = %u", b - a);
  return 0;
}

根据我个人的理解,单条asm指令通常比函数调用要快。 为什么在这种情况下 fcos 这么慢?


更新: 我在另一台装有 i7-6700HQ 的笔记本电脑上运行了相同的代码。 在这台笔记本电脑上,1000000 次 fcos 仅花费 51 毫秒。为什么两个cpu差别这么大。

【问题讨论】:

  • 查看程序集以了解cos() 会发生什么。
  • 至少用你正在使用的实现来标记它,因为除了古怪风格的内联汇编是特定于实现的之外,数学库的性能属性和死代码消除也将是。
  • 它可能使用流式 SIMD 扩展而不是旧的、未进一步优化的 x87 指令。
  • 哪个 i7 型号?范围从 2008 年的 Nehalem(fcos 解码到 ~100 微秒,需要 40 到 100 个时钟周期)到 2019 年的咖啡湖(fcos 解码到 53 到 105 微秒,需要 50 到 130 个时钟周期)@987654321 @。甚至 Cannon Lake... 数学库 cos() 可能使用的 SSE2 指令的性能范围很大。
  • @Peter Cordes 我的 CPU 是 i7 6820HQ。今天我尝试在 i7 6700HQ 的笔记本电脑上运行相同的代码。在 6700HQ 笔记本电脑上,asm fcos 花费 51ms。为什么两个cpu差别这么大。

标签: c assembly x86 floating-point x87


【解决方案1】:

我敢打赌答案很简单。您不使用cos 的结果,并且如本例所示对其进行了优化

https://godbolt.org/z/iw-nft

将变量更改为 volatile 以强制调用 cos

https://godbolt.org/z/9_dpMs

另一个猜测: 也许您的 cos 实现使用查找表。那么它会比硬件实现更快。

【讨论】:

  • 谢谢,但是我检查了反汇编和cos调用没有优化。此外,Visual Studio 的标准 c 数学库是否使用查找表?
猜你喜欢
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 2012-09-11
  • 2023-03-14
相关资源
最近更新 更多