我正在编写一个图像处理程序,以实时处理视频帧。它使用Emgu.CV库(C#)封装OpenCV库的dll(非托管C++)来实现。现在我必须编写自己的特殊算法,并且它需要尽可能快。
哪种实现方式会更快地执行算法?
在C#中编写一个不安全的函数
将该功能添加到OpenCV库中,并通过Emgu.CV进行调用。
我猜测C#的unsafe较慢,因为它需要通过JIT编译器,但是差别会很明显吗?
编辑:
在VS2008下为.NET 3.5编译
我正在编写一个图像处理程序,以实时处理视频帧。它使用Emgu.CV库(C#)封装OpenCV库的dll(非托管C++)来实现。现在我必须编写自己的特殊算法,并且它需要尽可能快。
哪种实现方式会更快地执行算法?
在C#中编写一个不安全的函数
将该功能添加到OpenCV库中,并通过Emgu.CV进行调用。
我猜测C#的unsafe较慢,因为它需要通过JIT编译器,但是差别会很明显吗?
编辑:
在VS2008下为.NET 3.5编译
它需要尽可能快。
那你问错问题了。
使用汇编语言编码,并针对您支持的每个重要的架构变体创建不同的版本。
使用优化良好的C++编译器的输出作为指南,因为它可能知道你不知道的一些技巧。但是你可能能想到一些改进,因为C++不一定向编译器传达所有可能有用于优化的信息。例如,C++没有C99关键字“限制”。尽管在这种特定情况下,许多C++编译器(包括MSVC)现在都支持它,因此请在可能的情况下使用它。
当然,如果你的意思是,“我希望它快速,但不要到超出C#或C++的程度”,那么答案就不同了;-)
我希望 C# 在很多情况下至少能接近类似的 C++ 的性能。我当然假定程序运行的时间足够长,JIT 本身需要的时间是无关紧要的,但如果你正在处理大量的视频,则似乎很可能。但我也希望有些事情,如果你在不安全的 C# 中执行它们,将比在 C++ 中等效的事情要慢得多。我不知道它们是什么,因为我所有关于 JIT 的经验都是在 Java 而不是 CLR 中。也可能有些事情在 C++ 中会更慢,例如,如果您的算法对 C# 代码进行任何回调。
不幸的是,确保它们多接近的唯一方法是编写两个版本并测试它们,这有点违背了写C++版本需要额外努力的初衷。但是,您可以通过黑客一些快速代码来近似处理您想要执行的处理,而不必执行全部或正确。如果您的算法将循环遍历所有像素并对每个像素执行少数FP运算,则拼凑一个大致的基准测试应该只需要半个小时。
通常我会建议不要开始思考“这需要尽可能快”。需求应该是可以实现的,而且“尽可能X”只是边缘可实现的。需求也应该是可测试的,“尽可能X”除非你知道一个理论上的极限,否则是不可测试的。更友好的要求是“这需要在这样的速度CPU上实时处理某分辨率的视频帧”,或者“这需要比我们主要竞争对手的产品更快”。如果C#版本可以达到这样的要求,并留有一点余地来考虑用户设定中意外的小问题,那么工作完成了。
这取决于算法、实现、C++编译器和JIT编译器。我猜大多数情况下C++实现会更快。但这可能会改变。
JIT 编译器可以针对您的代码运行的平台进行优化,而不是像 C++ 编译器那样为您的代码可能运行的所有平台平均优化。这是 JIT 编译器的新版本越来越擅长的事情,在某些情况下可能使 JIT 的代码具有优势。所以答案并不像您想象的那样明确。例如,新的 Java 热点编译器就做得非常好。
受控代码优于 C++ 的其他情况是需要分配和释放大量小对象的情况。.net runtime 预分配大块可重复使用的内存,因此在需要分配内存时不必每次都调用操作系统。
我不确定不安全的C#是否比普通的C#运行得更快。你也需要尝试一下。
如果你想知道你的情况的最佳解决方案,你需要尝试两种方式并且对比测量它们的差异。我认为不会有更多的。
语言没有“速度”。这取决于编译器和代码。在任何语言中都可能编写低效的代码,而聪明的编译器无论源语言如何都会生成接近最优化的代码。
C#和C++之间性能上唯一无法避免的因素就是C#应用程序在启动时必须执行更多操作(加载.NET框架,或许还需要即时编译一些代码),因此所有条件相同的情况下,它们的启动速度会稍慢一些。之后,这取决于具体情况,没有根本性的理由表明为什么一种语言必须永远比另一种语言快。
我也不知道不安全的 C# 为什么会比安全的更快。一般来说,安全是好的,因为它让编译器能够做出更强的假设,所以安全可能更快。但是,这还取决于你正在编译的代码、你正在使用的编译器以及其他十几个因素。
简言之,放弃认为你可以测量一种语言的表现的想法。你不能。一种语言从来没有“快”或“慢”这样的速度。它没有速度。
C#通常比C++慢。托管代码中有运行时检查。毕竟这就是它被托管的原因。例如,C++不必检查数组边界是否超出限制。
从我的经验来看,使用固定内存会有很大帮助。在.NET 4.0中有一个新的System.IO.UnmanagedMemoryAccessor类,可能在未来有所帮助。
If you are going to implement your algorithm in a standard way I think it s irrelevant. But some languages have bindings to apis or libraries that can give you a non standart boost.
考虑是否可以使用GPU处理- Nvidia和ATI提供CUDA和CTM框架,并且khronos组织(OpenGL)正在进行标准化努力。我的直觉告诉我,AMD将在其未来芯片中添加至少一个流处理器核心。因此,我认为这方面有相当大的前景。
试图查看是否可以利用SSE指令,有一些库可用-大多数是使用C ++或C编写,提供方便的API,请检查英特尔网站以获取方便的优化库,我记得有“英特尔性能原语”和“Math Kernel”。
但在政治方面,请将您的算法整合到OpenCV中,以便其他人也可以受益。
It s a battle that will rage on forever. C versus C++ versus C# versus whatever. In C#, the notion of unsafe is to unlock "dangerous" operations. ie, the use of pointers, and being able to cast to void pointers etc, as you can in C and C++. Very dangerous, and very powerful! But defeating what C# was based upon.
你会发现,现在微软在性能方面取得了长足的进步,特别是自.NET发布以来,而下一个版本的.NET实际上将支持内联方法,就像C++一样。这将增加特定情况下的性能。我讨厌这不是c#的特性,而是编译器检测到的讨厌属性-但你不能拥有一切。
就我个人而言,我正在使用C#和托管的DirectX编写游戏(为什么不用XNA?? 超出了这篇文章的范围)。在图形情况下,我正在使用不安全的代码,这说明了其他人所说的方向。
It s only because pixel access is rediculously slow with GDI++ that I was driven to look for alternatives. But on the whole, the c# compiler is pretty damned good, and for code comparisons (you can find articles) you ll find the performance is very comparable to c++. That s not to say there isn t a better way to write the code.
到最后,我个人认为C,C++和C#在执行时速度大致相同。只是在某些痛苦的情况下,您想要与底层硬件紧密合作或非常接近那些像素,您会发现C / C ++人群有明显优势。
But for business, and most things nowadays, C# is a real contender, and staying within the "safe" environment is definitely a bonus.
When stepping outside, you can get most things done with unsafe code, as I have - and boy, have I gone to some extremes! But was it worth it? Probably not. I personally wonder if I should have thought more along the lines of time-critical code in C++, and all the Object Oriented safe stuff in C#. But I have better performance than I thought I d get!
只要您小心处理Interop调用的数量,就可以同时享受两个世界的好处。我个人已经避免了这种情况,但我不知道代价是多少。
我尚未尝试的一种方法,但我很想听听体验,实际上是使用C++.NET开发库-这是否比c#的不安全对于这些特殊的图形情况更快?与本机C++编译代码相比如何?现在有个问题!
嗯。。
如果你了解你的环境并使用一个优秀的编译器(对于在Windows上的视频处理,Intel C++编译器可能是最佳选择),C++会在几个方面完胜C#:
malloc()
or any other dynamic allocator is nondeterministic, and almost all non-native languages force heavier heap usage, and thus heavier allocation).如果您使用不良的编译器,或者无法定位良好的芯片组,那么一切皆不确定。
老实说,你用哪种语言写并不是非常重要,最重要的是你使用什么算法(在我看来)。也许通过转换成本地代码,你可以使你的应用程序更快,但也可能使它变慢——这取决于编译器,程序的编写方式,如果你使用混合环境会产生什么样的互操作成本等等。你不可以没有分析就下定论。(另外,你有对你的应用程序进行分析吗?你真的知道它在哪里消耗时间吗?)
一个更好的算法与你选择的语言完全无关。
我有点晚回复,但我可以给你一些轶事经验。我们有一些矩阵乘法例程,最初用指针和不安全代码编码的C#。这在我们的应用程序中被证明是一个瓶颈,然后我们使用pinning+P/Invoke调用一个C++版本的矩阵乘法例程,得到了2倍的改进。这是一段时间以前的.NET 1.1,所以现在可能会更好。正如其他人指出的,这证明什么也没有,但这是一个有趣的练习。
我也同意thAAAnos的观点,如果你的算法确实需要“尽可能快”,则应利用IPL,或者如果必须的话,考虑GPU实现。