c++ - 显式类型转换与使用类型规则

标签 c++ optimization

假设我有这个程序:

#include <iostream>

using namespace std;
int main() {
    unsigned int n, i;
    double sum = 0;
    cout << "\n No. of terms: ";
    cin >> n;
    for( i=1; i<=n; i++ ) {
        sum += i/(i+1.0);       //// THE LINE IN QUESTION
    }
    cout << " Sum = " << sum;
    return 0;
}

它计算系列的总和:1/2 + 2/3 + 3/4 .. 到 n/n+1。

现在我想问一下,在我想将 int 值赋给双变量 sum 的 for 循环中,我可以通过两种方式做到这一点:

  1. 方法一:sum += i/(i+1.0)
  2. 方法 2:sum += (double) i/(i+1)

哪个更快或更好?

Lightth races in orbits :我的意思是应该使用哪种方法。

最佳答案

根据经验,此类微小差异可能无关紧要。在大约 20 个左右的周期(大部分由部门占用)中,有一个或两个周期的差异,如果有的话。

这些是您的两个方法执行的操作:

方法一

a   = (double)i; // convert to double
b   = 1.0;       // load double
c   = a + b;     // double addition
sum = a / c;     // double division

请注意,我们只需要对 double 进行一次转换,因为编译器可以进行称为公共(public)子表达式消除的优化。在许多机器(如 x86)上,您不能简单地将浮点常量添加到数字中,您必须先将常量加载到浮点寄存器中,因此我将其视为额外指令。如果您在循环中执行此操作,则 1.0 只需加载一次。

方法二

a   = (double)i; // convert to double
b   = i + 1;     // int addition
c   = (double)b; // convert to double
sum = a / c;     // double division

这里我们需要做两次转换,但我们可以节省浮点负载,我们可以用更便宜的整数加法代替浮点加法。

机器码

这是两种方法的 amd64 汇编:

method1:
        pxor     %xmm0, %xmm0      // clear result register
        movsd    .one(%rip), %xmm1 // load 1.0
        cvtsi2sd %edi, %xmm0       // convert int to double
        addsd    %xmm0, %xmm1      // double addition
        divsd    %xmm1, %xmm0      // double division

.one:
        .double 1.0

method2:
        pxor     %xmm0, %xmm0      // clear result register
        pxor     %xmm1, %xmm1      // clear register for i + 1
        cvtsi2sd %edi, %xmm0       // convert int to double
        addl     $1, %edi          // increment
        cvtsi2sd %edi, %xmm1       // convert int to double
        divsd    %xmm1, %xmm0      // double division

这两种方法在操作方面似乎相当相似。如果您想确定,我建议您对此进行基准测试。

关于c++ - 显式类型转换与使用类型规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32035761/

相关文章:

c++ - 全局变量是否意味着更快的代码?

c++ - Constexpr变量不是编译时值吗?

C++ 正则表达式,解析

php - 使用命名空间时 PHP 自动加载器的过程/流程

Mysql存储函数中的查询优化

c++ - 在 CLion 中编辑默认的 main.cpp 文件

c++ - GetVersionEx 弃用 - 如何从较新的 API 获取产品类型 (VER_NT_DOMAIN_CONTROLLER)

.net - 反序列化文件中的数据。性能问题

optimization - J:关于将过滤器序列最佳应用到列表

string - Rust 编程竞赛中最快的惯用 I/O 例程?