【问题标题】:performance of reciprocal calculation in c++c++中倒数计算的性能
【发布时间】:2016-01-26 14:18:57
【问题描述】:

有什么方法可以在不损失精度的情况下提高 的计算性能?目前我只是在做:

1 / (1 + a * b)

ab 是双倍的。 a 的值是常数。我需要做数百万次这样的计算。

【问题讨论】:

  • 您需要多少精度?
  • 预计算 ra=1/a 以便您可以使用 ra/(ra+b) 应该是在不损失精度的情况下略微提高速度。但我仍然希望更广泛地了解您实际尝试优化的内容。
  • 您有个人资料吗?这条线是瓶颈吗?通常循环是瓶颈的原因,而不是单个语句。虽然众所周知,除法会占用执行时间。
  • 你考虑过定点算法吗?定点比浮点更准确。
  • 如果你每次使用计算倒数一次,为什么你有多余的乘法?为什么不f/(1+a*b) ?另外,再一次,您为什么要谈论优化“数百万”次完成的事情?数百万是微不足道的。

标签: c++ performance math inverse


【解决方案1】:

a == 0a != 0,让我们分开,

  • 如果a == 0,那么答案是1(晶莹剔透)
  • 如果a ==!0,让c = 1/a

c 也是常量)然后整个表达式变为

    c / (b + c)

这将保存一个乘法计算。

【讨论】:

  • 你需要使用结合律和分配律来简化表达式。不幸的是,浮点数学既不是分布式的,也不是关联的。假设它是,可能会导致精度损失。我希望看到没有精度损失的证据。
  • 您是否想知道准确性的“损失”或只是准确性的变化?当然,这种改变会改变结果。更改后的结果是否或多或少是一个更复杂的问题。我不认为有理由相信它会变得不那么准确(除非您处于旧架构中,其中 double 的中间值保持在 80 位)。
  • 我喜欢a==0 的支票。同样,应检查b==0。比较比除法快。但是,由于ab 是浮点数,因此比较零很困难。必须与 epsilon 值进行比较,而不是与零完全等价。
  • 在原帖中,a 是常数,所以得到互惠是一次性的工作。
  • 在某些编程环境中(例如 NVIDIA GPU 上的 CUDA),倒数计算可能比全除法快得多,因此建议的转换可能会加快代码速度或使其变慢。不幸的是,提问者没有提供足够的背景信息来评估这种风险。
【解决方案2】:

看起来您必须迭代地计算给定的表达式(数百万次)。只要您有迭代过程 - 您可以考虑并行。在特定情况下,我会考虑 SIMD(向量)并行性。

现代 x86 处理器具有各种 SIMD 并行指令变体,用于“打包”(即 SIMD 并行)除法和“打包”(SIMD 并行)倒数,精度不同。

这意味着如果您能够“矢量化”您的迭代算法(使用现代编译器、OpenMP4.x 等编译指示等)并在支持 AVX 的现代 x86 硬件上运行生成的应用程序(Sandy Bridge 或更高版本,即 2011 年之后发布),那么 Compiler 很可能会根据您选择的浮点精度编译选项使用高效且快速的向量 parallel 除法或倒数(或 newton-rhapson 方案)。在某些平台上,打包(并行)除法几乎与标量(顺序)除法一样快,同时一次处理 4-16 个以上的元素。反过来,倒数比除法快得多。

这里是打包的 AVX 和 AVX512 除法/倒数指令的列表,可以给你一些想法(RCP 代表 Reciprocal。PS 代表并行单精度浮点,PD 代表并行双精度 FP,DIV 代表用于除法。AVX - 是您的 CPU 从 ~2011 年开始支持的内容。AVX-512 是一些“CPU”将从 ~2016 年下半年开始支持的内容)

  • ISA |说明 |准确性
  • AVX | VRCPS(无 DP)| 2^-12
  • AVX、AVX2 | VDIVPD/PS
  • AVX-512F | VRCP14PD/PS | 2^ -14
  • AVX-512F | VDIVPD/PS | 53 位??
  • AVX-512ER| VRCP28PD/PS | 2^ -28?

【讨论】:

    猜你喜欢
    • 2015-12-03
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    • 1970-01-01
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    相关资源
    最近更新 更多