- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我们正在使用 C# 和 .NET Core 处理 RTS game engine。与大多数其他实时多人游戏不同,RTS 游戏倾向于将玩家输入同步给其他玩家,并同时在所有客户端上同步运行游戏模拟。这要求游戏逻辑是确定性的,这样游戏就不会失去同步。
不确定性的一个潜在来源是浮点运算。据我所知,主要问题是旧的 x87 FPU 指令 - 它们使用内部 80 位寄存器,而 IEEE-754 浮点值是 32 位或 64 位,因此从寄存器移动时值会被截断到内存中。对代码和/或编译器的小改动可能会导致在不同时间发生截断,从而导致结果略有不同。不确定性也可能是由于意外使用不同的 FP 舍入模式引起的,但如果我理解正确的话,这基本上是一个已解决的问题。
我还有 gotten the impression,SSE(2) 指令不会遇到截断问题,因为它们在没有更高精度寄存器的情况下以 32 位或 64 位执行所有浮点运算。
最后,据我所知,CLR 在 x86 上使用 x87 FPU 指令(或者至少在 RyuJIT 之前是这样),在 x86-64 上使用 SSE 指令。我不确定这是否意味着所有或大多数操作。
.NET Core 最近添加了对准确 single precision math 的支持,如果这很重要的话。
但是在研究是否可以在 .NET 中确定性地使用 float 时,有很多答案是否定的,尽管它们主要涉及运行时的旧版本。
那么,如果 CoreCLR 在 x86-64 上使用 SSE FP 指令,是否意味着它不会遇到截断问题和/或任何其他与 FP 相关的非确定性问题?我们将 .NET Core 与引擎一起发布,因此每个客户端都将使用相同的运行时,并且我们会要求玩家使用完全相同版本的游戏客户端。限制引擎仅在 x86-64(在 PC 上)上工作也是一个可接受的限制。
如果运行时仍然使用结果不可靠的 x87 指令,使用软件浮点实现(如上面答案中链接的那个)来计算单个值是否有意义,并使用新的 hardware intrinsics 加速 SSE 的矢量运算?我已经对此进行了原型(prototype)设计,它似乎可行,但没有必要吗?
如果我们只能使用普通的浮点运算,有什么我们应该避免的,比如三角函数吗?
最后,如果到目前为止一切正常,当不同的客户端使用不同的操作系统甚至不同的 CPU 架构时,这将如何工作?假设实现没有错误,现代 ARM CPU 是否会遇到 80 位截断问题,或者相同的代码是否会以与 x86 相同的方式运行(如果我们排除三角函数等更棘手的东西)?
最佳答案
So, if CoreCLR uses SSE FP instructions on x86-64, does that mean that it doesn't suffer from the truncation issues, and/or any other FP-related non-determinism?
如果您继续使用 x86-64 并且在任何地方都使用完全相同的 CoreCLR 版本,那么它应该是确定性的。
If the runtime still uses x87 instructions with unreliable results, would it make sense to use a software float implementation [...] I've prototyped this and it seems to be work, but is it unnecessary?
这可能是解决 JIT 问题的解决方案,但您可能必须开发一个 Roslyn 分析器,以确保您在不经过这些操作的情况下不使用浮点运算......或者编写一个 IL 重写器,它将为您执行此操作(但这会使您的 .NET 程序集依赖架构......根据您的要求,这可能是可以接受的)
If we can just use normal floating point operations, is there anything we should avoid, like trigonometric functions?
据我所知,CoreCLR 正在将数学函数重定向到编译器 libc,因此只要您保持在同一版本、同一平台上,就应该没问题。
Finally, if everything is OK so far how would this work when different clients use different operating systems or even different CPU architectures? Do modern ARM CPUs suffer from the 80-bit truncation issue, or would the same code run identically to x86 (if we exclude trickier stuff like trigonometry), assuming the implementation has no bugs?
您可能会遇到一些与额外精度无关的问题。例如,对于 ARMv7,次正规 float 被刷新为零,而 aarch64 上的 ARMv8 将保留它们。
假设您继续使用 ARMv8,我不太清楚 ARMv8 的 JIT CoreCLR 在这方面是否表现良好;您可能应该直接在 GitHub 上询问。还有 libc 的行为可能会破坏确定性结果。
我们正致力于在 Unity 中解决这个问题,使用我们的“突发”编译器将 .NET IL 转换为 native 代码。我们在所有机器上使用 LLVM codegen,禁用一些可能破坏确定性的优化(所以在这里,总体上我们可以尝试保证跨平台编译器的行为),我们还使用 SLEEF 库来提供确定性计算数学函数(例如参见 https://github.com/shibatch/sleef/issues/187 )……所以可以做到。
在你的位置上,我可能会尝试调查 CoreCLR 是否真的对 x64 和 ARMv8 之间的普通浮点运算具有确定性......如果它看起来没问题,你可以调用这些 SLEEF 函数而不是 System.Math
它可以开箱即用,或者建议 CoreCLR 从 libc 切换到 SLEEF。
关于c# - .NET Core 中 gamedev 的浮点确定性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53989518/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!