C# 性能 - 我应该用 c++ 编写计算量大的方法吗?
我正在构建一个定量库的原型,该库使用图像处理技术进行一些信号分析。我完全用C#构建了最初的原型,但性能并没有预期的那么好。大部分计算都是通过繁重的矩阵计算来完成的,这些都占用了大部分时间。
我想知道为非托管 C++ 代码编写 C++/CLI 接口是否值得。有人经历过这个吗?欢迎提出其他优化 C# 性能的建议。
I am building a prototype for a quantitative library that does some signal analysis using image processing techniques. I built the initial prototype entirely in C#, but the performance is not as good as expected. Most of the computation is done through heavy matrix calculations, and these are taking up most of the time.
I am wondering if it is worth it to write a C++/CLI interface to unmanaged C++ code. Has anyone ever gone through this? Other suggestions for optimizing C# performance is welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
曾经有一段时间,用 C/C++ 编写肯定会更好,但现在 C# 优化器和 JIT 非常好,对于纯数学来说,可能没有什么区别。
当您必须处理内存和可能的数组时,就会出现差异。即便如此,我仍然会使用 C#(或 F#),然后优化热点。 JIT 非常擅长优化小的、短命的对象。
对于数组,您必须担心 C# 对每次访问进行边界检查。阅读此内容:
链接
自己测试一下——我发现 C# 具有可比性——有时更快。
There was a time where it would definitely be better to write in C/C++, but the C# optimizer and JIT is so good now, that for pure math, there's probably no difference.
The difference comes when you have to deal with memory and possibly arrays. Even so, I'd still work with C# (or F#) and then optimize hotspots. The JIT is really good at optimizing away small, short-lived objects.
With arrays, you have to worry about C# doing bounds-checks on each access. Read this:
Link
Test it yourself -- I've been finding C# to be comparable -- sometimes faster.
在这里很难给出明确的答案,但如果性能是一个问题,我会找到一个经过时间考验的库,具有您需要的性能并包装它。
像乘法或除法这样简单的事情在 C++ 和 C# 之间没有太大区别 - C++ 编译器有一个优化器,而 CLR 运行时有按需 JITer 来进行优化。因此理论上,c++ 仅在第一次调用时才会优于 c#。
然而,理论和实践并不相同。对于更复杂的算法,您还会遇到内存管理器之间的差异以及优化技术的成熟度。如果您想要轶事证据,您可以找到一些数学- 这里有大量的比较。
就我个人而言,我发现在本机库中进行繁重的计算并使用 c++/CLI 调用它可以在计算成为最大瓶颈时提供良好的提升。与往常一样,在进行任何优化之前请确保情况如此。
It's hard to give a definitive answer here, but if performance is an issue I'd find a time-tested library with the performance you need and wrap it.
Something simple like multiplication or division is not much different between c++ and c# - the c++ compiler has an optimizer, and the CLR runtime has the on-demand JITer that does optimizations. So in theory, the c++ would outperform c# only on the first call.
However, theory and practice are not the same. With more complicated algorithms you also run into the differences between memory managers, and the maturity of the optimization techniques. If you want anecdotal evidence, you can find some math-heavy comparisons here.
Personally, I find doing the heavy computations in a native library and using c++/CLI to call it gives a good boost when the computations are the biggest bottleneck. As always, make sure that's the case before doing any optimization.
在我看来,矩阵数学最好在本机代码中完成。即使是 C++ 库通常也允许绑定到较低级别的实现,例如 LAPACK。
此处有一个 C# LAPACK 端口(同一站点上还有 C# BLAS),您可以使用它可以尝试,但如果这比本机代码更快,我会感到惊讶。
Matrix math is best done in native code in my opinion. Even the C++ libraries typically allow binding to a lower-level implementation like LAPACK.
There is a C# LAPACK port here (also C# BLAS on the same site) which you could try but I'd be surprised if this is faster than native code.
我在 C# 中完成了大量图像处理工作,是的,我通常使用本机代码来执行性能很重要的重型代码,但我只使用 PInvoke,而不是 C++/CLI 接口。不过,很多时候这是不需要的。
有很多优秀的 .NET 分析器。 Red Gate 是我个人的最爱。它可能会帮助您直观地了解瓶颈所在。
I've done a lot of image processing work in C# and, yes, I usually do use native code for heavy duty code where performance matters but I used just PInvokes and not the C++/CLI interface. A lot of time this is not needed, though.
There's quite a few good .NET profilers. The Red Gate one is my personal favorite. It might help you to visualize where the bottlenecks are.
唯一合理的语言基准:http://shootout.alioth.debian.org/
查看你自己。
The only reasonable language benchmark out there: http://shootout.alioth.debian.org/
See for yourself.
C# 中的数学计算性能相当差。我惊讶地发现 C# 中的数学计算有多慢。只需用 C# 和 C++ 编写一个循环,其中包含一些乘法、Sin、Cos...,差异是巨大的。
我不知道托管 C++,但在非托管 C++ 中实现所有这些,我想通过 P/Invoke 公开粒度接口应该不会对性能造成太大影响。
这就是我为繁重的实时图像处理所做的工作。
Performance for mathematical computation is pretty poor in C#. I was gobbsmacked to find how slow mathematical calculations are in C#. Just write a loop in C# and C++ having a few Multiplication, Sin, Cos, ... and the difference is immense.
I do not know Managed C++ but imlpementing it all in unmanaged C++ abd I would umagine exposing granular interfaces through P/Invoke should have little perfromance hit.
That is what I have done for heavy real-time image processing.
那么您有两个选择:
用 C++ 构建另一个原型,并查看其比较情况,或者优化您的 C# 代码。无论您使用哪种语言编写,在您对其进行分析和优化之前,您的代码都不会很快。在 C++ 中尤其如此。如果您用 C# 编写最快的实现,并将其与 C++ 中最快的实现进行比较,那么 C++ 版本很可能会更快。但这会以开发时间为代价。编写高效的 C++ 代码并非易事。如果您是这门语言的新手,那么您很可能会编写效率非常低的代码,特别是如果您来自 C# 或 Java,因为它们的工作方式不同并且成本不同。
如果您只是编写一个工作实现,而不用过多担心性能,那么我猜测 C# 版本可能会更快。
但这实际上取决于您追求什么样的性能(尤其是您需要执行的操作的成本有多大)。从托管代码到本机代码的转换会产生开销,因此对于短操作来说不值得经常执行的
C++ 中的数字运算代码可以与 Fortran 中编写的代码一样快(相差几个百分点),但要实现这一点,您需要使用很多高级技术。 (表达式模板和大量元编程)或一些为您实现它的相当复杂的库
值得吗?或者 C# 是否可以足够快以满足您的需求?
then you have two options:
Build another prototype in C++, and see how that compares, or optimize your C# code. No matter what language you write in, your code won't be fast until you've profiled and optimized and profiled and optimized it. That is especially true in C++. If you write the fastest possible implementation in C# and compare it to the fastest possible implementation in C++, then the C++ version will most likely be faster. But it will come at a cost in terms of development time. It's not trivial to write efficient C++ code. If you are new to the language then you will most likely write very inefficient code, especially if you are coming from C# or Java, where things are done differently and have different costs.
If you just write a working implementation, without worrying too much about performance, then I'm guessing that the C# version will probably be faster.
But it really depends on what kind of performance you're after (and not least, how expensive the operations you need to perform are. There's an overhead associated with the transition from managed to native code, so it is not worth it for short operations that are executed often.
Number-crunching code in C++ can be as fast as code written in Fortran (give or take a few percent), but to achieve that, you need to use a lot of advanced techniques (expression templates and lots of metaprogramming) or some fairly complex libraries which implement it for you.
Is that worth it? Or can C# be made fast enough for your needs?
您应该用 C++ 编写计算量大的程序,通过优化 C# 无法达到接近 C++ 的性能。假设计算需要相当长的时间,调用包装器的开销可以忽略不计。我曾经使用 C++ 和 C# 进行过编码,但从未见过 .NET 框架代码与 C++ 相媲美的情况。在某些情况下,C# 运行得更好,但它更好是因为缺乏适当的库或 C++ 中的编码不好。如果你能用 C# 和 C++ 编写同样好的代码,我会用 C++ 编写性能代码,而其他一切都用 C#。
如果 x 是世界上最好的 C++ 程序员,y 是最好的 C# 程序员,那么大多数时候 x 可以写出比 y 更快的代码。然而,大多数时候 y 可以比 x 更快地完成编码。
You should write computational heavy programs in C++, you cannot reach anywhere near to C++ performance by optimizing C#. The overhead of calling wrappers is negligible assuming the computation takes considerable time. I have done coding in both C++ and C# and have never seen any occasion where .NET framework code come comparable to C++. There are a few instances where C# where runs better, but it was better because of lack of appropriate libraries or bad coding in C++. If you can write code equally well in C# and C++, I would write performance code in C++ and everything else is C#.
If x is the world best C++ programmer and y is the best C# programmer then most of the times x can write faster code than y. However, y can finish the coding faster than x most of the times.