从 C# 访问数学协处理器
Posted
技术标签:
【中文标题】从 C# 访问数学协处理器【英文标题】:Accessing math coprocessor from C# 【发布时间】:2011-03-17 21:53:07 【问题描述】:如何从 C# 代码访问数学协处理器?我想尽可能快地对整数进行一些计算。我知道在 C++ 编译器下可以在其中使用汇编程序代码,但是 .Net 呢?
【问题讨论】:
你能给我们举个例子来说明你正在尝试做什么。在大多数情况下,JIT 编译器发出的代码足够快。 顺便说一句,自 1989 年 80486DX 以来,数学已停止在 协处理器中硬连线。IIRC 80387 协处理器是关于 FP 算术,而不是整数;-) 【参考方案1】:JIT 编译器知道数学协处理器并将使用它。您真正想要的是使用 SIMD 引擎,而不是数学协处理器。这是 JIT 编译承诺的一部分,运行时可以选择每台计算机上可用的最快硬件加速,但我认为 .NET 实际上并没有这样做,至少在 v4 中。
或者您是否使用术语“数学协处理器”来表示 x87 FPU 以外的其他东西?有一些 FPGA 板作为加速器/协处理器系统销售。如果这就是您的意思,您需要查阅特定产品随附的编程手册。没有特殊的 CPU 指令可以访问这些指令,在这种情况下,内联汇编程序不会有帮助。
例如,GPU 在大型数据集上的数学运算速度甚至比 CPU 的 SIMD 引擎还要快,您可以使用 DirectX Compute Shaders(或 p/调用 OpenCL)从 .NET 访问它,无需汇编程序。
【讨论】:
本是正确的。运行时几乎不区分处理器架构。它没有受益于最新的处理器指令。这样做的原因是,这将使 Microsoft 在所有这些处理器上测试框架变得更加困难,并使 Microsoft 支持人员更难重现问题,因为 JITted 代码会因处理器而异。 是的,我的意思是 X87,感谢您提供的有用答案。我将尝试使用 DirectX 并将其与 C# 进行比较【参考方案2】:我认为这不可能直接从托管代码中完成。您仍然可以调用执行这些计算的非托管代码,但是很难说互操作封送处理的成本是否值得。您必须尽可能地减少它,并在非托管代码中进行所有计算,并且只进行一次调用以最大限度地减少开销。
【讨论】:
我过去曾参与过一个我们进行贷款计算的项目。一位开发人员将计算转移到 C++,因为他认为 C# 太慢了。 C++ 中的计算实际上并不是必须更快,但是编组杀死了我们。具有讽刺意味的是,真正的性能问题实际上是在计算期间执行的数百个数据库查询占用了大约 98% 的时间:-) @Steven:当然可以,但我敢打赌你很容易就找到了瓶颈。 C# 和 C++ 中的数学代码可能没有明显不同,但我敢打赌人们注意到了移植 db access api 的痛苦。【参考方案3】:不,您不能在 C# 托管代码中直接使用内联汇编程序。
最好的办法是确保您的通用方法/算法干净高效,数学运算干净高效,然后依靠编译器来有效利用可用的协处理器。
【讨论】:
我说:并行!计算通常是非常好的并行化候选者。算法越简洁,并行化就越容易。 @Steven:听起来像是一个很棒的建议,假设它在 OP 正在做的事情的背景下是有意义的。 当然。我们目前没有足够的信息来了解并行化是否适用于他的情况。只是一个有根据的猜测:-)【参考方案4】:C# 作为一种语言,.NET 作为框架也不支持这一点。
如果您需要那种那种速度或能力,请完全使用其他东西。
【讨论】:
您的用户名的好答案。【参考方案5】:我知道这是一篇旧帖子,但对于那些出于加速数学运算(例如大量矢量运算)的类似原因来到这里的人。 为了在数学中从 C# 中获得最大的速度,您应该将公式转换为对数等值。这需要一些练习,但是一旦你有了想法,你就可以用每个公式来做。然后决定将您的值保留为日志形式,仅将用户需要查看的值转换为人类可读的形式。
日志工作得更快的原因是因为它们都是加法和减法(减法只是加一个补码),您的处理器可以轻松地大量执行这些操作。
如果您在有在线课程引导您完成之前没有学过这种数学,它有一个学习曲线,但对于数学/图形程序员来说,学习曲线是值得的。
【讨论】:
FP 乘法与大多数现代 x86 CPU(如 Skylake 或 Ice Lake)上的 FP 加法/减法(吞吐量、延迟和微指令)具有相同的性能。或者你在谈论整数?我想这对除法有帮助,因为 div 和 sqrt 很慢(延迟更高,吞吐量更差),如果这就是你的意思吗? 不,不是真的,这些值看起来很小,但在实时处理中它们很重要。此链接指向旧帖子,但百分比差异仍然适用。 ithare.com/infographics-operation-costs-in-cpu-clock-cycles 此外(双关语的不好的地方),日志的加法/(减法)允许序列化正在添加的数据。 对不起,我应该链接uops.info 来支持我的观点。 Agner Fog 的指令表(您的链接引用)具有相同的编号。您的链接似乎只是将吞吐量显示为“成本”范围的低端,而延迟显示为高端,这对于我猜不了解流水线 CPU 和指令级并行性的读者可能有用。自从 Skylake 以来,英特尔在vaddpd
和 vmulpd
的性能几乎相同,延迟为 4c,吞吐量为 0.5c,单 uop。 (并且编译器可以将乘法和加法的组合“收缩”到 FMA 中。)
所以基本上我是说你链接的表关于 FP add 与 FP mul 是错误的。在 Haswell 上,FP add 是 3 个周期延迟(1c 吞吐量),FP mul 是 5 个周期延迟(0.5c 吞吐量),因此有趣的是,尽管延迟更好,但 FP add 的吞吐量更差。 Why does Intel's Haswell chip allow floating point multiplication to be twice as fast as addition?(此外,将整数 SIMD mul 与 FP mul 合并会推高范围的顶部,例如,对于 Haswell 及更高版本的 vpmulld
,它应该是 10 个周期延迟。)
基本上,试图将事情减少到可以加起来的简单成本是一项愚蠢的差事,that's not how pipelined OoO exec CPUs work,尽管我有attempted it myself in a Q&A answer。以上是关于从 C# 访问数学协处理器的主要内容,如果未能解决你的问题,请参考以下文章