仰望—星空 2023-07-18 20:36 采纳率: 93.3%
浏览 28
已结题

__forceinline无效

#函数调用为什么那么慢?
我找到两种快速求绝对值的计算方法:
第一种为:

__forceinline int my_abs1(const int& value)
{
    return (value ^ (value >> 31)) - (value >> 31);
}

第二种为:

__forceinline int my_abs2(const int& value)
{
    return value * (1 - (value >> 31) << 1);
}

测试代码为:

int main()
{
    int c = 1000000000;

    clock_t start_time = clock();
    for (int i = 0; i < c; i++)
    {
        abs(1);
        abs(-1);
    }
    clock_t end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;

    start_time = clock();
    for (int i = 0; i < c; i++)
    {
        my_abs1(1);
        my_abs1(-1);
    }
    end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;

    start_time = clock();
    for (int i = 0; i < c; i++)
    {
        my_abs2(1);
        my_abs2(-1);
    }
    end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;
}

结果:9406、11442、11318

最终两种快速运算绝对值的函数反而使用时间更久,于是我直接计算而不调用函数:

int main()
{
    int c = 1000000000;

    clock_t start_time = clock();
    for (int i = 0; i < c; i++)
    {
        abs(1);
        abs(-1);
    }
    clock_t end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;

    start_time = clock();
    for (int i = 0; i < c; i++)
    {
        (1 ^ (1 >> 31)) - (1 >> 31);
        (-1 ^ (-1 >> 31)) - (-1 >> 31);
    }
    end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;

    start_time = clock();
    for (int i = 0; i < c; i++)
    {
        1* (1 - (1 >> 31) << 1);
        -1* (1 - (-1 >> 31) << 1);
    }
    end_time = clock();
    std::cout << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC * 1000 << std::endl;
}
结果为:936621452147。
可以得出这两种方法确实更快,但是第一次测试我使用了__forceinline也使用了引用为实参,为什么会满那么多?而且对比的对象是普通的C++abs函数,都是函数调用,为什么代价这么大?

#我正在寻找最快速的求绝对值方法,是否有int和float的快速求绝对值方法?

  • 写回答

1条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2023-07-18 21:29
    关注

    该回答引用ChatGPT-3.5,仅供参考,不保证完全正确

    首先,关于你的第一个问题,为什么使用__forceinline和引用参数对于这两种快速求绝对值的函数没有产生性能提升。在C++中,使用__forceinline关键字可以提示编译器尝试将函数内联展开,以减少函数调用的开销。然而,编译器是否实际进行内联展开,还取决于编译器的具体实现和优化设置。


    在你的测试中,你使用了clock()函数来测量函数调用的时间开销。然而,clock()函数并不是一个精确的计时器,而且在不同的编译器和平台上可能会有不同的行为。因此,通过clock()函数来测量函数调用的性能差异可能并不准确。


    此外,现代编译器在进行优化时,通常会对常见的函数调用进行内联展开,如abs()函数。因此,在你的测试中,对于简单的函数调用,编译器可能已经进行了适当的内联展开,使得性能与手动展开的函数相当。


    至于你的第二个问题,如何更快地计算int和float类型的绝对值,这里有一些常见的方法:

    1. 对于int类型,可以使用位操作和条件判断来计算绝对值,例如:

      int abs(int value) {
       int mask = value >> (sizeof(int) * CHAR_BIT - 1);
       return (value + mask) ^ mask;
      }
      

      这种方法利用了整数的符号位来生成一个掩码,然后将掩码与原始值相加,再异或掩码,即可得到绝对值。

    2. 对于float类型,可以使用union和位操作来计算绝对值,例如:

      float abs(float value) {
       union {
           float f;
           uint32_t i;
       } u;
       u.f = value;
       u.i &= 0x7FFFFFFF;  // 将符号位置0
       return u.f;
      }
      

      这种方法通过将float类型的值视为32位整数,并将符号位置0来得到绝对值。

    需要注意的是,以上方法可能在不同的平台和编译器上产生不同的结果,且性能差异可能不明显。对于绝对值这样的简单操作,现代的编译器通常已经对其进行了高度优化,因此手动优化可能带来的性能提升可能是微乎其微的。如果性能是你的主要关注点,建议使用编译器优化选项,如-O2或-O3,让编译器自行处理这些优化。


    总结来说,对于简单的函数调用,编译器通常能够进行适当的优化,因此手动展开函数可能不会带来明显的性能提升。同时,现代的编译器已经对常见的操作进行了高度优化,手动优化的效果可能有限。如果性能是关键需求,建议使用编译器的优化选项,并进行基于实际测试的性能优化。


    该回答引用NewBing,仅供参考,不保证完全正确

    __forceinline是一个编译器特定的关键字,用于强制将函数内联,即将函数的代码直接插入到调用点,而不是通过函数调用的方式执行。这样可以减少函数调用的开销,提高程序的运行速度。但是,__forceinline并不保证一定会内联,编译器可能会根据其他因素决定是否内联。__forceinline也可能导致代码体积增大,缓存命中率降低等问题。__forceinline是一个非标准的扩展,不同的编译器可能有不同的实现和语法。¹²


    求绝对值的方法有很多种,不同的方法可能在不同的平台和场景下有不同的效率。一般来说,求绝对值的方法可以分为以下几类:

    • 使用标准库函数abs或fabs,这些函数通常会被编译器优化为最适合目标平台的指令或代码。³
    • 使用条件表达式或分支语句,如x > 0 ? x : -xif (x > 0) return x; else return -x;,这些方法可能会引入分支预测错误的开销,但也可能被编译器优化为条件传送指令,无分支。⁴
    • 使用位运算或算术运算,如(x ^ (x >> 31)) - (x >> 31)x * (1 - (x >> 31) << 1),这些方法可以避免分支,但也可能引入其他开销,如移位、异或、乘法等。⁵
    • 使用浮点数的特性,如将符号位清零,这种方法只适用于IEEE 754标准的浮点数,并且需要类型转换或联合体等技巧。⁶

    要确定哪种方法最快,最好是在目标平台上进行实际的测试和比较,并考虑数据分布、编译器优化、缓存效果等因素。

    ¹: inline vs __inline vs inline vs __forceinline? - Stack Overflow
    ²: How to #define __forceinline inline? - Stack Overflow
    ³: abs(3) - Linux manual page
    ⁴: C语言里求绝对值最快的办法是什么? - 知乎
    ⁵: C语言里求绝对值最快的办法是什么? - 知乎
    ⁶: C语言里求绝对值最快的办法是什么? - 知乎


    源: 与必应的对话, 2023/7/18
    (1) inline vs __inline vs inline vs __forceinline? - Stack Overflow. https://stackoverflow.com/questions/2765164/inline-vs-inline-vs-inline-vs-forceinline.
    (2) gcc - How to #define __forceinline inline? - Stack Overflow. https://stackoverflow.com/questions/8897791/how-to-define-forceinline-inline.
    (3) __forceinline 内联函数_残月飞雪的博客-CSDN博客. https://blog.csdn.net/majinlei121/article/details/46118749.
    (4) 1.1.2 Java @ForceInline 注解用法_扶朕去网吧的博客-CSDN博客. https://blog.csdn.net/pxg943055021/article/details/125430078.
    (5) C语言里求绝对值最快的办法是什么? - 知乎. https://www.zhihu.com/question/23536224.
    (6) Excel计算数值绝对值的2种操作方法 - 知乎 - 知乎专栏. https://zhuanlan.zhihu.com/p/557463959.
    (7) inline vs __inline vs inline vs __forceinline? - Stack Overflow. https://stackoverflow.com/questions/2765164/inline-vs-inline-vs-inline-vs-forceinline.
    (8) gcc - How to #define __forceinline inline? - Stack Overflow. https://stackoverflow.com/questions/8897791/how-to-define-forceinline-inline.
    (9) C语言里求绝对值最快的办法是什么? - 知乎. https://www.zhihu.com/question/23536224.
    (10) C语言里求绝对值最快的办法是什么? - 知乎. https://www.zhihu.com/question/23536224.
    (11) C语言里求绝对值最快的办法是什么? - 知乎. https://www.zhihu.com/question/23536224.
    (12) Excel表格中怎么使用公式快速求数值的绝对值? - 脚本之家. https://www.jb51.net/office/excel/502432.html.
    (13) undefined. http://msdn.microsoft.com/en-us/library/z8y1yy88%28VS.71%29.aspx.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 7月27日
  • 已采纳回答 7月19日
  • 创建了问题 7月18日

悬赏问题

  • ¥15 已知平面坐标系(非直角坐标系)内三个点的坐标,反求两坐标轴的夹角
  • ¥15 webots有问题,无响应
  • ¥15 数据量少可以用MK趋势分析吗
  • ¥15 使用VH6501干扰RTR位,CANoe上显示的错误帧不足32个就进入bus off快慢恢复,为什么?
  • ¥15 大智慧怎么编写一个选股程序
  • ¥100 python 调用 cgps 命令获取 实时位置信息
  • ¥15 两台交换机分别是trunk接口和access接口为何无法通信,通信过程是如何?
  • ¥15 C语言使用vscode编码错误
  • ¥15 用KSV5转成本时,如何不生成那笔中间凭证
  • ¥20 ensp怎么配置让PC1和PC2通讯上