如何让 wine/Linux 对传输功能使用与 Windows 相同的精度?

How can I get wine/Linux to use the same accuracy for trascendental functions as Windows?

提问人:Emanuele 提问时间:5/13/2023 最后编辑:Emanuele 更新时间:5/23/2023 访问量:141

问:

我希望 wine/Linux 运行程序(即通过 wine 在 Linux 上运行的 Windows exe/dll)对 Microsoft 实现的传输功能(即 VS2019 等)使用相同的准确性。

我面临的挑战是,我需要通过 wine 运行的一些软件确实调用了这样的函数,我担心通过 glibc 提供的准确性/实现会产生不同的数字,并使代码最终遵循不同的路径。

我找到了一种解决方法,即加载ucrtbase.dll,如下所示native,builtin

WINEDLLOVERRIDES="ucrtbase=n,b" wine <my program>

当我通过交互式终端运行我的软件时,这非常有效。

不幸的是,如果我随后将这样的进程作为子进程运行(即 stdoutstderr 重定向到内存/文件),那么程序就会崩溃,因为我想它仍然认为它在终端上并尝试打印特殊颜色字符,但当然它不应该。 当然,如果我离开内置ucrtbase.dll,它都可以作为子进程工作,但是我失去了准确性/结果。

知道我接下来该如何进行吗?我也可以自己在内置葡萄酒ucrtbase.dll中重新编译一些超越函数,使其与VS2019相同(以及进一步),唉,不确定源代码是否公开可用?

C Linux 可视化工作室-2019 wine crt

评论

1赞 Eric Postpischil 5/13/2023
精度不是问题。准确性也不高。您正在寻找的是可重复性。搜索“[浮点]可重复性”会显示有关该主题的多个问题。精度是执行计算或返回结果的精细度。对于通常用于 的格式,这与 Linux 和 Windows 相同,除了例程内部使用的任何扩展精度计算外,因此精度不是问题。准确性不是问题,因为例程的两个实现可能同样准确,但方式不同......double
0赞 Eric Postpischil 5/13/2023
...由于超越函数的性质,它们是近似的,常用的近似不能完全提供正确的四舍五入的结果。基本上有两种方法可以获得超越函数的可重现结果:使用提供正确舍入结果的实现,这些结果是必要的,或者在程序的所有版本中使用相同的实现......
0赞 Eric Postpischil 5/13/2023
...仅仅重新编译相同的源代码可能不足以做到这一点;您需要确保执行相同的浮点运算,但不同的编译器可能会将相同的 C 源代码编译为不同的汇编,例如使用 FMA 或扩展精度硬件功能。
0赞 Emanuele 5/13/2023
我用“精确”作为“准确性”,是的,你是对的,我不是以英语为母语的人。无论如何,我想我传达了我面临的问题。有什么针对葡萄酒的建议,而不是通用的东西吗?恭敬地,你的回答没有用,只是迂腐。
1赞 Steve Summit 5/13/2023
@Emanuele 埃里克的评论比术语问题要多得多!特别是,可重复性问题——以及超越函数并不总是在所有实现下都能给出正确舍入的结果这一事实——是问题的根本原因。

答:

0赞 Emanuele 5/23/2023 #1

最有效和最高效的方法是使用来自 Windows 安装的原始版本(包含所有超越功能)(当然,这需要您拥有许可副本)并添加到您的 wine 选项中,例如:ucrtbase.dll

WINEDLLOVERRIDES="ucrtbase=n,b" wine <your program>

这是非常谨慎的,因为只要从终端(或终端模拟器)运行,当运行时,一切都会起作用。 相反,如果必须将其输出重定向到文件,则会遇到内存损坏和/或崩溃。<your program>

为了解决这个问题,基本上有两种选择:

  1. 软关闭和/或调用 - 不会打印任何内容std::coutstd::cerrstd::cout.setstate(std::ios_base::eofbit)
  2. 更改输出内容的位置和/或通过重定向相同的内容(沿着此答案的行)似乎现在这个库知道它不会打印到终端,因此它不会损坏流/内存std::coutstd::cerr

这应该发生在内部,并且可以通过更改核心 DLL 之一来通过 wine 轻松实现,以便可以在程序启动时通过 DllMain/ 执行相同的内容<your program>DLL_PROCESS_ATTACH

这已在 RHEL 7.9 上的 wine 8.0.1 中得到验证。