为什么优化会改变 double 到 unsigned int 转换的结果?

问题描述 投票:0回答:1

鉴于此代码:(https://godbolt.org/z/qGneEne7x)

#include <stdio.h>
#include <xmmintrin.h>

int main ()
{
    double d[2] = { 161785254.0, -215713672.0 };
    int i[4];
    unsigned u[4];

    __m128d vd = _mm_loadu_pd(d);
    __m128i vi = _mm_cvtpd_epi32(vd);
    _mm_storeu_si128((void *)i, vi);
    _mm_storeu_si128((void *)u, vi);

    printf("Doubles to convert            : %.1f %.1f\n", d[0], d[1]);
    printf("\n");
    printf("SIMD double to signed int     : %i   %i\n", i[0], i[1]);
    printf("SIMD double stored to unsigned: %u   %u\n", u[0], u[1]);
    printf("\n");
    printf("Scalar double to signed int   : %i   %i\n", (int)d[0], (int)d[1]);
    printf("Scalar double to unsigned     : %u   %u\n", (unsigned)d[0], (unsigned)d[1]);
}

为什么优化会改变标量代码中双精度到无符号转换的结果?

这就是用 -O0 打印出来的内容:

Doubles to convert            : 161785254.0 -215713672.0

SIMD double to signed int     : 161785254   -215713672
SIMD double stored to unsigned: 161785254   4079253624

Scalar double to signed int   : 161785254   -215713672
Scalar double to unsigned     : 161785254   4079253624

一切都如预期。

打开-O1,无符号标量变为零:

Scalar double to unsigned     : 161785254   0

这是为什么?

double unsigned
1个回答
0
投票

由于编译器和优化设置的工作方式,优化可能会更改 double 到 unsigned int 转换的结果。当执行从 double 到 unsigned int 的转换时,实际上是截断 double 的小数部分并将剩余的整数部分转换为无符号整数。此转换的结果取决于 double 的值以及 C 或 C++ 标准定义的规则。

但是,当应用优化时,编译器可能会做出某些假设或执行可能影响结果的转换。优化可能改变结果的一些原因包括:

  1. 编译器特定的行为:不同的编译器可能有不同的优化策略,并且在优化代码时可能不会严格遵循相同的规则,尤其是在非标准转换方面。

  2. 浮点精度:浮点数(如双精度)的精度有限。应用优化时,编译器可能会决定以更高的精度执行某些操作以避免精度损失,或者可能会进行其他影响浮点值的中间表示的转换。

  3. 表达式求值:编译器可能在优化期间重新排序或组合表达式,这可能会改变运算顺序,并导致从 double 转换为 unsigned int 时得到不同的结果。

  4. 未定义的行为:如果 double 的值超出了 unsigned int 的可表示范围,则根据 C 和 C++ 标准,该行为是未定义的。在这种情况下,优化可能会产生意想不到的结果,甚至导致崩溃。

为了避免从 double 转换为 unsigned int 时出现意外行为,必须确保 double 的值在 unsigned int 的范围内,并以不依赖于特定编译器优化或行为的方式编写代码。您还可以使用显式类型转换来使编译器清楚您的意图,但您仍然应该意识到与精度和范围相关的潜在问题。

© www.soinside.com 2019 - 2024. All rights reserved.