【问题标题】:Using P/invoke to improve performance, feasible or just wishful thinking?使用 P/invoke 来提高性能,可行还是只是一厢情愿?
【发布时间】:2023-03-25 22:08:02
【问题描述】:

这是一个我可能应该早点问的问题,但我并没有急于在 MonoTouch 中使用 p/invoke 类型的东西。

基本上我在与大量浮点运算有关的性能方面存在问题,特别是涉及最小/最大函数、向量乘法和类似的东西(基本上检测不同类型的形状是否相交)。

这些操作的原因是因为使用 C# 编写的 2D 物理引擎。

在 Windows Phone 7 和 Xbox 360 等一些平台上,物理引擎运行时没有任何问题,它会占用一些 CPU 周期,但会留下足够的时间来确保游戏以稳定的帧速率运行。

问题在于在 iPhone 上运行的 MonoTouch。看起来 MonoToch 并不是那么好,有这么多的浮点运算,iPhone(甚至 iPad 2)发现自己受到了严重的影响,物理是明显的性能瓶颈。我有profiled the performance,它归结为一组相对基本的数学函数,如I mentioned before,没有真正优化这些函数的方法,物理引擎本身写得很好,我看不到它有什么明显的地方落后,坦率地说,我怀疑它作为 2D C# 物理引擎有什么问题。

为此,我决定找到一个用 C(或 C++,如果可能)编写的物理引擎,并将其与 MonoTouch 主应用程序连接起来。我的理由是,由于 MonoTouch 中的性能问题可能与 MonoTouch 编译器无法编译 .net 代码以像 Wp7/xbox 360 JIT 编译器一样快(这是可以理解的)将事情从 monotouch 中移出这一事实有关并在本地运行它们将有助于提高性能。

所以我的想法是,我将使用 Box2D,编写一堆静态包装函数(例如 CreateWorld()、CreateBox()、GetBodyPosition(int id) 等)并通过 p/hook 所有这些调用功能并将其全部集成到我的物理包装类中,这样核心游戏逻辑将需要最少甚至不需要修改,并且我可以保持原始代码设计的完整性,但由于物理正在运行而获得性能提升原生 C.

但这让我想到,性能问题源于非常简单直接的数学函数、简单的乘法和大小比较。如果通过 p/invoke 运行函数可以提高速度,那么只需将 Vector2.Max 之类的函数重写为 C 函数并调用也可以提高性能?

然而这似乎有点牵强,如果是这样的话,Mono不会这样做吗?

所以我想我的总体问题是,从 p/invoke 调用静态链接的本机库时,性能是否比 MonoTouch 编译的等效 C# 函数更好?

【问题讨论】:

    标签: c# c performance xamarin.ios pinvoke


    【解决方案1】:

    实际上只有一种方法可以确定它是否更快:对您的案例进行基准测试。可能是您用于本机库的 c 编译器能够比 mono 的 jit 进行更多优化,也可能只是 CPU 不适合您的特定工作负载。

    如果您想尝试使用本机库,请记住,您不想经常从托管调用本机代码,每次托管到本机转换都会对性能造成重大影响(影响程度取决于很多因素,但转换次数越少越好)。

    也就是说,我个人的猜测是,mono jit 不能很好地处理浮点运算(以前在某些 cpu 上存在过这个问题,我现在不记得这些问题是否仍然存在也不是在哪个 cpus 上),因此您将从使用本机库中受益。

    【讨论】:

    • 您是否遇到与拇指编译有关的问题?我不确定这是否是单声道特定的,但我已经确定将其关闭,因为据称它对浮点运算有性能影响。我的目标是在托管代码中做尽可能少的操作,并将尽可能多的操作推迟到本地,基本上整个物理引擎将在本地运行,并且只会交互最少的次数以在托管端保持值更新(即状态场景,所有身体的位置等)。
    • 问题可能与拇指编译有关,我不确定,我只记得在某处读过一些关于浮点数学问题的内容。不过,您的方法看起来很适合从本机代码中获得所有可能的好处。
    【解决方案2】:

    如果您的代码有一些关键部分,您可以尝试使用“不安全”来避免对数组访问进行自动范围检查。对于诸如 2 或 3 向量之类的短数组和简单的操作(例如范数或点积),它可能会产生影响。

    简单的数学运算不应该更慢,但是如果没有分析结果,就很难判断代码的哪些部分更慢。如果原生版本大量使用 sse 或者您的托管版本无意中使用了大量装箱等,可能会导致差异。

    要使 P/invoke 有用,您应该执行一些可以完成大量工作的调用,因此如果您可以在一次调用本机 dll 中更新整个状态,这可能会很有用。但我绝对不会尝试将琐碎的函数原生化。

    【讨论】:

      【解决方案3】:

      除了 Rolf 的出色响应之外,您还可以考虑在构建游戏时使用 LLVM 优化。

      令我惊讶的是,Windows Phone 7 的 JIT 比 Mono 的静态编译器更好

      【讨论】:

      • 我确实使用 LLVM 编译,但遗憾的是改进是微不足道的。您是否认为 WP7 硬件可能比 iPhone4 硬件更强大,因此为什么 WP7 在相同的代码上管理更好的帧率?它们都有 1ghz 处理器,但来自不同的供应商。尽管如此,必须具有比 WP7 更好的规格的 iPad 2 仍然落后于游戏并且提供比 WP7 设备更差的帧率......
      • 我很想看到你的代码运行缓慢,我们可以用分析器看看它
      • 我很乐意让你看一下代码,给我发电子邮件到 jabberworx@gmail.com 并且我会把项目发给你
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-12
      • 2012-08-13
      • 1970-01-01
      • 1970-01-01
      • 2012-03-27
      • 1970-01-01
      相关资源
      最近更新 更多