24

我正在编写一个图像处理程序来执行视频帧的实时处理。它在 C# 中使用包装 OpenCV 库 dll(非托管 C++)的 Emgu.CV 库(C#)。现在我必须编写自己的特殊算法,并且它需要尽可能快。

哪个将是算法的更快实现?

  1. 在 C# 中编写“不安全”函数

  2. 将函数添加到OpenCV库并通过Emgu.CV调用

我猜 C# unsafe 速度较慢,因为它通过 JIT 编译器,但差异会很大吗?

编辑:

在 VS2008 下为 .NET 3.5 编译

4

10 回答 10

71

它需要尽可能快

那你问错问题了。

用汇编程序对其进行编码,您支持的每个重要架构变体都有不同的版本。

使用经过优化的优秀 C++ 编译器的输出作为指导,因为它可能知道一些您不知道的技巧。但是您可能会想到一些改进,因为 C++ 不一定会将所有可能对优化有用的信息传达给编译器。例如,C++ 没有 C99 关键字限制。尽管在这种特殊情况下,许多 C++ 编译器(包括 MSVC)现在都支持它,但请尽可能使用它。

当然,如果您的意思是“我希望它快一点,但不要超出 C# 或 C++ 的范围”,那么答案就不同了 ;-)

我希望 C# 在很多情况下至少能够接近外观相似的 C++ 的性能。我当然假设该程序将运行足够长的时间,以至于 JIT 本身所花费的时间是无关紧要的,但如果您正在处理大量视频,那么这似乎很可能。但我也希望有一些事情,如果你在不安全的 C# 中做这些事情,会比 C++ 中的同等事情慢得多。我不知道它们是什么,因为我对 JIT 的所有经验都是在 Java 而不是 CLR 中。在 C++ 中可能还有一些较慢的东西,例如,如果您的算法对 C# 代码进行任何调用。

不幸的是,唯一能确定两者有多接近的方法是同时编写并测试它们,这有点忽略了编写 C++ 版本需要大量额外工作这一点。但是,您可以通过编写一些与您想要执行的处理近似的快速代码来获得一个粗略的想法,而不必全部完成或正确处理。如果您的算法要遍历所有像素并为每个像素执行一些 FP 操作,那么将粗略的基准测试组合在一起应该需要半个小时。

通常我会建议不要开始思考“这需要尽可能快”。要求应该是可以实现的,根据定义,“尽可能 X”只是可以实现的边界。需求也应该是可测试的,除非你知道理论上的最大值,否则“尽可能 X”是不可测试的。一个更友好的要求是“这需要在某某速度的 CPU 上实时处理某某分辨率的视频帧”,或者“这需要比我们主要竞争对手的产品更快”。如果 C# 版本做到了这一点,并留出一点余地来解决用户设置中的意外小问题,那么工作就完成了。

于 2008-11-11T11:36:29.037 回答
6

它取决于算法、实现、C++ 编译器和 JIT 编译器。我猜在大多数情况下,C++ 实现会更快。但这可能会改变。

JIT 编译器可以针对您的代码运行的平台优化您的代码,而不是像 C++ 编译器那样针对您的代码可能运行的所有平台进行平均。这是较新版本的 JIT 编译器越来越擅长的事情,并且在某些情况下可能会给 JITted 代码带来优势。所以答案并不像你想象的那么清楚。例如,新的 Java 热点编译器就可以很好地做到这一点。

托管代码可能比 C++ 做得更好的其他情况是您需要分配和释放大量小对象。.net 运行时预先分配了可重用的大块内存,因此它不需要在每次需要分配内存时调用操作系统。

我不确定 unsafe C# 的运行速度是否比普通 C# 快得多。你也得试试这个。

如果您想知道什么是适合您的情况的最佳解决方案,您必须尝试两者并衡量差异。我认为不会超过

于 2008-11-11T11:20:09.723 回答
6

语言没有“速度”。这取决于编译器和代码。用任何语言编写低效代码都是可能的,无论源语言是什么,一个聪明的编译器都会生成接近最优的代码。

C# 和 C++ 之间唯一真正不可避免的性能因素是 C# 应用程序在启动时必须做更多的事情(加载 .NET 框架,可能还 JIT 一些代码),所以在所有条件相同的情况下,它们的启动速度会慢一些。在那之后,这取决于,并且没有根本原因为什么一种语言必须总是比另一种更快。

我也不知道为什么不安全的 C# 应该比安全更快。一般来说,安全是好的,因为它允许编译器做出一些更强大的假设,因此安全可能更快。但同样,这取决于您正在编译的代码、您正在使用的编译器以及其他十几个因素。

简而言之,放弃可以衡量语言性能的想法。你不能。语言从来没有“快”或“慢”之分。它没有速度。

于 2008-11-11T11:26:39.133 回答
6

C# 通常比 C++ 慢。托管代码中有运行时检查。毕竟,这些都是使它受到管理的原因。例如,C++ 不必检查数组的边界是否已超出。

根据我的经验,使用固定内存有很大帮助。.NET 4.0 中有一个新的System.IO.UnmanagedMemoryAccessor类,将来可能会有所帮助。

于 2008-11-11T12:43:07.560 回答
4

如果您打算以标准方式实现您的算法,我认为这无关紧要。但是有些语言绑定了 api 或库,可以给你一个非标准的提升。

  1. 考虑是否可以使用 GPU 处理 - nvidia 和 ati 提供 CUDA 和 CTM 框架,并且 khronos 组 (openGL) 正在进行标准化工作。一种预感还告诉我,AMD 将在他们未来的芯片中添加至少一个流处理器内核。所以我认为在那个领域有很大的希望。

  2. 试着看看你是否可以利用 SSE 指令,周围有一些库——大多数是 C++ 或 C——提供方便的 api,检查英特尔的网站以获得方便的优化库,我确实记得“英特尔性能基元”和“数学内核”。

但在政治方面,请务必将您的算法纳入 OpenCV,以便其他人也可以从中受益。

于 2008-11-11T13:45:32.037 回答
4

这是一场将永远持续下去的战斗。C 与 C++ 与 C# 与其他任何东西。在 C# 中,不安全的概念是解锁“危险”操作。即,指针的使用,以及能够转换为 void 指针等,就像在 C 和 C++ 中一样。非常危险,而且非常强大!但是打败了 C# 的基础。

您会发现,如今,Microsoft 在性能方面取得了长足的进步,尤其是自 .NET 发布以来,并且 .NET 的下一个版本实际上将支持内联方法,就像您可以使用 C++ 一样。这将提高非常特定情况下的性能。我讨厌它不是 ac# 功能,而是编译器选择的一个讨厌的属性——但你不能拥有它。

就个人而言,我正在使用 C# 和托管 DirectX 编写游戏(为什么不使用 XNA??超出了本文的范围)。我在图形情况下使用了不安全的代码,这引起了对其他人所说的方向的认可。

只是因为 GDI++ 的像素访问速度非常慢,我才被迫寻找替代方案。但总的来说,c# 编译器非常好,代码比较(你可以找到文章)你会发现性能与 c++ 非常相似。这并不是说没有更好的方法来编写代码。

归根结底,我个人认为 C、C++ 和 C# 在执行时的速度大致相同。只是在一些痛苦的情况下,您希望与底层硬件密切合作或非常接近这些像素,您会发现 C/C++ 人群有明显的优势。

但是对于商业和当今的大多数事情来说,C# 是一个真正的竞争者,并且保持在“安全”环境中绝对是一个奖励。
走出去时,您可以使用不安全的代码完成大多数事情,就像我一样 - 天哪,我是否走极端了!但这值得吗?可能不是。我个人想知道我是否应该更多地考虑 C++ 中的时间关键代码,以及 C# 中的所有面向对象的安全内容。但我的表现比我想象的要好!

只要您谨慎处理所进行的互操作调用的数量,您就可以两全其美。我个人避免了这种情况,但我不知道要付出什么代价。

因此,一种我没有尝试过但很想听听冒险的方法,在实际使用 C++.NET 开发库时——对于这些特殊的图形情况,这会比 c# 的不安全更快吗?这与本机 C++ 编译代码相比如何?现在有一个问题!

唔..

于 2013-07-18T13:30:59.983 回答
3

如果您了解您的环境并且使用了良好的编译器(对于 Windows 上的视频处理,英特尔 C++ 编译器可能是最佳选择),C++ 将轻松击败 C#,原因如下:

  • C++ 运行时环境没有内在的运行时检查(缺点是你可以自由支配自己)。C# 运行时环境将进行一些健全性检查,至少在最初是这样。
  • C++ 编译器是为优化代码而构建的。虽然理论上可以使用 ICC(或 GCC)使用的所有优化 voodo 来实现 C# JIT 编译器,但微软的 JIT 能否可靠地做得更好是值得怀疑的。即使 JIT 编译器具有运行时统计信息,这仍然不如 ICC 或 GCC 中的配置文件引导优化。
  • C++ 环境允许您更好地控制内存模型。如果您的应用程序达到破坏数据缓存或使堆碎片化的地步,您将非常欣赏对分配的额外控制。哎呀,如果你能避免动态分配,你已经好很多了(提示:运行时间malloc()或任何其他动态分配器是不确定的,几乎所有非本地语言都强制使用更重的堆,因此更重的分配)。

如果你使用了一个糟糕的编译器,或者如果你不能定位一个好的芯片组,那么所有的赌注都没有了

于 2008-11-26T04:11:46.690 回答
2

老实说,你用什么语言编写它并不像你使用什么算法那么重要(无论如何,IMO)。也许通过使用本机代码,您可能会使您的应用程序更快,但也可能使其更慢——这取决于编译器、程序的编写方式、如果您正在使用会产生什么样的互操作成本混合环境等。如果不对其进行分析,您就不能真正说出来。(而且,就此而言,您是否分析过您的应用程序?您真的知道它在哪里花费时间吗?

更好的算法完全独立于您选择的语言。

于 2009-06-10T00:40:21.973 回答
1

我的回复有点晚,但我可以给你一些轶事经验。我们有一些矩阵乘法例程,这些例程最初是用 C# 使用指针和不安全代码编写的。这被证明是我们应用程序中的一个瓶颈,然后我们使用 pinning+P/Invoke 调用 C++ 版本的矩阵乘法例程,并获得了 2 倍的改进。这是不久前的 .NET 1.1,所以现在情况可能会更好。正如其他人指出的那样,这并不能证明任何事情,但这是一个有趣的练习。

我也同意 thAAAnos,如果你的算法真的必须“尽可能快”地利用 IPL,或者如果你必须考虑 GPU 实现。

于 2008-11-28T20:56:56.290 回答
-7

在 CPU 上运行总是比在 CPU 上的 VM 上运行要快。我无法相信人们试图以其他方式争论。

例如,我们的网络服务器上有一些相当繁重的图像处理工作正在排队。最初为了让它工作,我们使用了 PHP 的 GD 函数。

他们慢得要命。我们用 C++ 重写了我们需要的功能。

于 2008-11-11T11:37:41.967 回答