Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ FPU控制功能是否与x64_64处理器相关?_C++_C - Fatal编程技术网

C++ FPU控制功能是否与x64_64处理器相关?

C++ FPU控制功能是否与x64_64处理器相关?,c++,c,C++,C,我问这个问题是因为我试图在Visual Studio 2017(cl.exe)和gcc 5.4.0之间实现位(哈希)相等。有问题的函数使用sin()和cos()。所有变量都是双变量,FMAD也是相关的 我一直在SO和网络上广泛阅读有关浮点决定论、可复制性和锁存MP游戏设计的内容。我知道单编译器、单构建决定论并不难,但我正在尝试双编译器、单构建决定论 这里不关心效率。我只是想让结果吻合 我这样问是因为我希望缩小我对测试/尝试内容的顾虑 这些与x86_64处理器和构建相关吗 控制x87 fpu的函数

我问这个问题是因为我试图在Visual Studio 2017(cl.exe)和gcc 5.4.0之间实现位(哈希)相等。有问题的函数使用sin()和cos()。所有变量都是双变量,FMAD也是相关的

我一直在SO和网络上广泛阅读有关浮点决定论、可复制性和锁存MP游戏设计的内容。我知道单编译器、单构建决定论并不难,但我正在尝试双编译器、单构建决定论

这里不关心效率。我只是想让结果吻合

我这样问是因为我希望缩小我对测试/尝试内容的顾虑

这些与x86_64处理器和构建相关吗

  • 控制x87 fpu的函数
  • XPFPA{声明、还原等}

  • “大多数浮点函数必须以某种方式执行舍入。C/C++标准在这个问题上相当模糊,IEEE对三角函数的一致性不够严格。这意味着在实践中,试图以可移植的方式压缩编译器默认数学实现的正确四舍五入是无用的

    例如,/的libm实现(由gcc使用)是在汇编中编写的,对于不同的体系结构,算法是不同的,并且很可能取决于库的版本

    因此,您有两种可能性:

    • 仅使用带精确舍入的浮点运算(融合乘法累加+泰勒级数)实现您自己的正弦/余弦
    • 使用具有强烈舍入考虑的第三方库
    我个人在处理舍入错误时将库用作金标准。这将带来运行时成本,尽管我从未尝试根据libm性能对其进行基准测试


    自定义实现

    请注意,如果您决定自己实现它,则需要选择舍入模式并通知编译器这对您很重要

    在C++中,这样做是:

    #include <cfenv>
    #pragma STDC FENV_ACCESS ON
    #pragma STDC FP_CONTRACT OFF
    
    int main(int, char**) {
        ...
        if(!std::fesetround(FE_TONEAREST))
            throw std::runtime_error("fesetround failed!");
        ...
    }
    
    #包括
    #布拉格STDC FENV_通道
    #布拉格STDC FP_合同关闭
    int main(int,char**){
    ...
    如果(!std::fesetround(feu TONEAREST))
    抛出std::runtime_错误(“fesetround失败!”);
    ...
    }
    
    gcc和MSVC使用不同的标准库,因此trig函数的实现可能不同。除此之外,SIMD的不同硬件实现可以给出不同的答案。在两个平台上使用相同的第三方数学库(例如MKL)可能会更幸运。根据我的经验,如果您能够在两种平台上始终获得精确的按位结果,您将是幸运的。也许你已经读过了——一个mcve演示这个问题会很有用。我认为如果你想让sin/cos相同,那么你需要使用相同的实现(即找到/创建这些函数的实现,并将它们包含到你的项目中)。这是因为SSE没有sin/cos,所以它们是通过某种算法实现的。不同的库将为您提供不同的保证(唯一的例外是,如果它们保证使用相同的舍入得到最精确的结果)。您可能会发现这很有用。例如,crlibm为sin/cos提供正确的舍入结果(我没有使用此库)。此答案最能解决我的问题;这是(最有可能的)不同平台和构建的sin/cos实现。如果没有人在x64上发布关于FPU的答案,我会选择这个。注意,我不会在游戏引擎中使用MPFR。它被设计成尽可能精确(精确的四舍五入),这对于您的目的来说可能太贵了。在您的情况下,我会选择自定义实现,但不要忘记使用std::fesetround和STDC pragma设置舍入模式。