【问题标题】:Denormalized floating point in Objective-C?Objective-C中的非规范化浮点?
【发布时间】:2012-03-10 04:25:39
【问题描述】:

堆栈溢出问题/答案Why does changing 0.1f to 0 slow down performance by 10x? 与 Objective-C 有什么相关性?如果有任何相关性,这应该如何改变我的编码习惯?有什么方法可以关闭 Mac OS X 上的非规范化浮点吗?

这似乎与 iOS 完全无关。对吗?

【问题讨论】:

    标签: c++ objective-c performance floating-point


    【解决方案1】:

    正如我在回复您的评论时所说的那样:

    这更像是 CPU 而不是语言问题,所以它可能有 与 x86 上的 Objective-C 相关。 (iPhone的ARMv7好像不支持 非规范化的浮点数,至少使用默认的运行时/构建设置)

    更新

    我刚刚测试过。在 x86 上的 Mac OS X 上观察到减速,在 ARMv7 上的 iOS 上则没有(默认构建设置)。

    不出所料,在 iOS 模拟器(在 x86 上)上运行的非规范化浮点数再次出现。

    有趣的是,FLT_MIN 和 DBL_MIN 分别被定义为最小的非规范化数字(在 iOS、Mac OS X 和 Linux 上)。使用

    会发生奇怪的事情
    DBL_MIN/2.0
    

    在您的代码中;编译器很高兴地设置了一个非规范化的常量,但是一旦(arm)CPU 接触到它,它就会被设置为零:

    double test = DBL_MIN/2.0;
    printf("test      == 0.0 %d\n",test==0.0);
    printf("DBL_MIN/2 == 0.0 %d\n",DBL_MIN/2.0==0.0);
    

    输出:

    test      == 0.0 1  // computer says YES
    DBL_MIN/2 == 0.0 0  // compiler says NO
    

    所以快速运行时检查是否支持非规范化可以是:

    #define SUPPORT_DENORMALIZATION ({volatile double t=DBL_MIN/2.0;t!=0.0;})
    

    (“即使没有任何适用性的默示保证”)

    这是 ARM 在清零模式下所说的:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204h/Bcfheche.html

    更新

    这是在 ARMv7 上禁用刷新为零模式的方法:

    int x;
    asm(
        "vmrs %[result],FPSCR \r\n"
        "bic %[result],%[result],#16777216 \r\n"
        "vmsr FPSCR,%[result]"
        :[result] "=r" (x) : :
    );
    printf("ARM FPSCR: %08x\n",x);
    

    得到以下令人惊讶的结果。

    • 第 1 列:浮点数,每次迭代除以 2
    • 第 2 列:此浮点数的二进制表示
    • 第 3 列:将此浮点数求和 1e7 次所需的时间

    您可以清楚地看到非规范化的成本为零。 (对于 iPad 2。在 iPhone 4 上,它的代价是降低了 10%。)

    0.000000000000000000000000000000000100000004670110: 10111100001101110010000011100000 110 ms
    0.000000000000000000000000000000000050000002335055: 10111100001101110010000101100000 110 ms
    0.000000000000000000000000000000000025000001167528: 10111100001101110010000001100000 110 ms
    0.000000000000000000000000000000000012500000583764: 10111100001101110010000110100000 110 ms
    0.000000000000000000000000000000000006250000291882: 10111100001101110010000010100000 111 ms
    0.000000000000000000000000000000000003125000145941: 10111100001101110010000100100000 110 ms
    0.000000000000000000000000000000000001562500072970: 10111100001101110010000000100000 110 ms
    0.000000000000000000000000000000000000781250036485: 10111100001101110010000111000000 110 ms
    0.000000000000000000000000000000000000390625018243: 10111100001101110010000011000000 110 ms
    0.000000000000000000000000000000000000195312509121: 10111100001101110010000101000000 110 ms
    0.000000000000000000000000000000000000097656254561: 10111100001101110010000001000000 110 ms
    0.000000000000000000000000000000000000048828127280: 10111100001101110010000110000000 110 ms
    0.000000000000000000000000000000000000024414063640: 10111100001101110010000010000000 110 ms
    0.000000000000000000000000000000000000012207031820: 10111100001101110010000100000000 111 ms
    0.000000000000000000000000000000000000006103515209: 01111000011011100100001000000000 110 ms
    0.000000000000000000000000000000000000003051757605: 11110000110111001000010000000000 110 ms
    0.000000000000000000000000000000000000001525879503: 00010001101110010000100000000000 110 ms
    0.000000000000000000000000000000000000000762939751: 00100011011100100001000000000000 110 ms
    0.000000000000000000000000000000000000000381469876: 01000110111001000010000000000000 112 ms
    0.000000000000000000000000000000000000000190734938: 10001101110010000100000000000000 110 ms
    0.000000000000000000000000000000000000000095366768: 00011011100100001000000000000000 110 ms
    0.000000000000000000000000000000000000000047683384: 00110111001000010000000000000000 110 ms
    0.000000000000000000000000000000000000000023841692: 01101110010000100000000000000000 111 ms
    0.000000000000000000000000000000000000000011920846: 11011100100001000000000000000000 110 ms
    0.000000000000000000000000000000000000000005961124: 01111001000010000000000000000000 110 ms
    0.000000000000000000000000000000000000000002980562: 11110010000100000000000000000000 110 ms
    0.000000000000000000000000000000000000000001490982: 00010100001000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000745491: 00101000010000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000372745: 01010000100000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000186373: 10100001000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000092486: 01000010000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000046243: 10000100000000000000000000000000 111 ms
    0.000000000000000000000000000000000000000000022421: 00001000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000011210: 00010000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000005605: 00100000000000000000000000000000 111 ms
    0.000000000000000000000000000000000000000000002803: 01000000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000001401: 10000000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 110 ms
    0.000000000000000000000000000000000000000000000000: 00000000000000000000000000000000 110 ms
    

    【讨论】:

    • @Yar:我会说:用-ffast-math 编译,但无论我设置什么标志,它都拒绝刷新为零。
    • @Yar:不确定,从一些小的值开始,每轮除以 2。然后,如果您发现一些有趣的阈值,您可以与预定义的常量进行比较。
    • @Yar:“特别是 Java 编程语言需要支持 IEEE 754 非规范化浮点数和逐渐下溢”(来源:java.sun.com/docs/books/jls/second_edition/html/…)
    • @Yar:对于 java,我得到完全相同的结果。一旦你低于Float.MIN_NORMAL (~1E-38) for float,速度会降低 50 倍。
    • @Yar:当然这取决于 CPU;之前的评论是关于 x86,如果你在 ARM(dalvik VM、Android)上运行,你可以在不减速的情况下使用非规范化的 1E-45。
    猜你喜欢
    • 2021-06-13
    • 2014-05-19
    • 1970-01-01
    • 2013-02-14
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多