【问题标题】:OpenCV: C++ and C performance comparisonOpenCV:C++ 和 C 性能比较
【发布时间】:2012-07-07 17:58:05
【问题描述】:

现在我正在使用 OpenCV API (C++) 开发一些应用程序。此应用程序会处理视频。

在 PC 上,一切都运行得非常快。今天我决定将这个应用程序移植到 Android 上(使用摄像头作为视频输入)。幸运的是,有适用于 Android 的 OpenCV,所以我只是将我的本机代码添加到示例 Android 应用程序中。除了性能,一切都很好。我对我的应用程序进行了基准测试,发现该应用程序以 4-5 fps 运行,这实际上是不可接受的(我的设备具有单核 1ghz 处理器) - 我希望它以大约 10 fps 的速度运行。

C 上完全重写我的应用程序是否有意义?我知道使用 std::vector 这样的东西对开发人员来说很舒服,但我不在乎。

OpenCV's C 接口似乎与C++ 接口具有相同的功能/方法。

我用谷歌搜索了这个问题,但没有找到任何东西。

感谢您的建议。

【问题讨论】:

  • 我对 android 不是特别熟悉,但是使用 OpenCV 的 C 接口并没有给您带来任何显着的性能提升,因为它仍然使用相同的基本代码。
  • 我在回答中添加了更多信息,希望对您有用。

标签: c++ c performance opencv


【解决方案1】:

我在Android和优化方面做了很多工作(我写了一个4ms处理一帧的视频处理应用程序)所以希望能给你一些中肯的答案。

OpenCV 中的 C 和 C++ 接口没有太大区别。一些代码是用 C 编写的,并且有一个 C++ 包装器,而一些反之亦然。两者之间的任何显着差异(由 Shervin Emami 衡量)要么是回归,要么是错误修复,要么是质量改进。你应该坚持使用最新的 OpenCV 版本。

为什么不重写?

你会花很多时间,你可以更好地利用这些时间。 C 接口很繁琐,引入错误或内存泄漏的机会很高。在我看来,你应该避免它。

优化建议

A.开启优化。

编译器优化和调试断言的缺乏都会对您的运行时间产生很大影响。

B. 描述您的应用。

首先在您的计算机上执行此操作,因为它更容易。使用 Visual Studio Profiler,识别慢速部分。优化它们。永远不要因为你认为慢而优化,而是因为你衡量它。从最慢的功能开始,尽可能优化它,然后再慢一点。衡量您的更改以确保它确实更快。

C. 专注于算法。

更快的算法可以将性能提高几个数量级 (100x)。 C++ 技巧可能会给您带来 2 倍的性能提升。

经典技巧:

  • 将视频帧调整为更小。通常,您可以从 200x300 像素的图像中提取信息,而不是 1024x768。第一个的面积要小10倍。

  • 使用更简单的操作而不是复杂的操作。使用整数而不是浮点数。并且永远不要在矩阵中使用 double 或在执行数千次的 for 循环中使用。

  • 尽可能少地进行计算。您能否仅在图像的特定区域中跟踪对象,而不是针对所有帧进行全部处理?您能否对非常小的图像进行粗略/近似检测,然后在全帧的 ROI 上对其进行细化?

D.在重要的地方使用 C

在循环中,使用 C 风格而不是 C++ 可能更有意义。指向数据矩阵或浮点数组的指针比 mat.at 或 std::vector 快得多。通常瓶颈是嵌套循环。专注于它。到处替换 vector 并把你的代码意大利化是没有意义的。

E.避免隐藏成本

一些 OpenCV 函数将数据转换为双精度,对其进行处理,然后再转换回输入格式。当心它们,它们会破坏移动设备的性能。示例:翘曲、缩放、类型转换。此外,众所周知,色彩空间转换是惰性的。更喜欢直接从原生 YUV 获得的灰度。

F.使用矢量化

ARM 处理器使用称为 NEON 的技术实现矢量化。学会使用它。它很强大!

一个小例子:

float* a, *b, *c;
// init a and b to 1000001 elements
for(int i=0;i<1000001;i++)
    c[i] = a[i]*b[i];

可以改写如下。它更冗长,但速度更快。

float* a, *b, *c;
// init a and b to 1000001 elements
float32x4_t _a, _b, _c;
int i;
for(i=0;i<1000001;i+=4)
{  
    a_ = vld1q_f32( &a[i] ); // load 4 floats from a in a NEON register
    b_ = vld1q_f32( &b[i] );
    c_ = vmulq_f32(a_, b_); // perform 4 float multiplies in parrallel
    vst1q_f32( &c[i], c_); // store the four results in c
}
// the vector size is not always multiple of 4 or 8 or 16. 
// Process the remaining elements
for(;i<1000001;i++)
    c[i] = a[i]*b[i];

纯粹主义者say 你必须用汇编程序编写,但对于普通程序员来说,这有点令人生畏。我使用gcc intrinsics 得到了很好的结果,就像上面的例子一样。

另一种快速启动的方法是将 OpenCV 中的手动编码 SSE 优化代码转换为 NEON。 SSE 是 Intel 处理器中的 NEON 等价物,许多 OpenCV 函数都使用它,例如 here。这是 uchar 矩阵(常规图像格式)的图像过滤代码。不能一味地一一转换指令,而是以它为例。

您可以在this blog 和以下帖子中阅读有关 NEON 的更多信息。

G.注意抓图

在移动设备上运行速度可能会慢得惊人。优化它是特定于设备和操作系统的。

【讨论】:

  • 您对如何轮询相机有什么建议吗?在 Nexus 4 上使用 OpenCV 2.4.3.2 的示例,注释掉任何处理,我在大多数分辨率下只能看到 10fps,如果我降低到 176x144,则为 20fps....
  • 不要使用 OpenCV 相机 API。使用 Java API 捕获帧,并将它们传递给本机代码。
  • 谢谢!我在想我必须走那条路,调整事情就像他们在 iOS 中所做的那样。你会认为至少会有一个针对吞吐量量身定制的 OpenCV 示例......
【解决方案2】:

在做出任何此类决定之前,您应该分析您的代码以定位代码中的热点。如果没有这些信息,您为加快速度所做的任何更改都将是猜测。你试过这个Android NDK profiler?

【讨论】:

  • 感谢您的回复-我会试试的。
  • @Astor 如果这不起作用,您总是可以使用在调试器中反复暂停应用程序的老技巧,以了解它大部分时间花在哪里。跨度>
【解决方案3】:

shervin imami 在他的网站上进行了一些性能测试。您可以查看它以获得一些想法。

http://www.shervinemami.info/timingTests.html

希望对你有帮助。

(另外,如果你能在某处分享你自己的发现,如果你有任何提高性能的方法。)

【讨论】:

  • 感谢您的回复 - 我会查看该测试并创建自己的测试。
【解决方案4】:

我想这个问题需要表述为:C 比 C++ 快吗?答案是否定的。两者都被编译为本地机器语言,C++ 被设计为与 C 一样快 至于 STL(尤其是 ISO 标准)也被设计并注意它们与指针一样快 + 它们提供了灵活性。 使用 C 的唯一原因是您的平台不支持 C++ 在我谦虚的开放中,不要将所有内容都转换为 C,因为您可能会获得几乎相同的性能。而是尝试改进您的代码或使用 opencv 的其他功能来做您想做的事。

不相信?然后写一个简单的函数,一次用C,一次用C++,循环运行1亿次,自己测量时间。也许这有助于您做出正确的决定

【讨论】:

    【解决方案5】:

    我从未在 Android 中使用过 C 或 C++。但是在 PC 中,您可以让 C++ 与 C 代码一样快(有时甚至更快)。大多数 C++ 都是专门为允许更多功能而设计的,但不以速度为代价(模板在编译时解决)。大多数编译器都非常擅长优化您的代码,并且您的 std::vector 调用将被内联,并且代码几乎与使用原生 C 数组相同。

    我建议您寻找另一种提高性能的方法。也许Android中有一些多媒体硬件扩展,您可以访问并使用它来优化代码。

    【讨论】:

      【解决方案6】:

      我在多次测试中注意到:

      1. 直接访问像素而不是使用 Mat.at(x,y) 方法时,C 接口 (IplImage) 的速度要快很多倍,当我将 C++ 应用程序转换为 C 时,性能提高了 3 倍在我的斑点检测例程中

      2. 当从外部应用程序(例如 LabView)调用某些例程时,C++ 接口在某些例程中崩溃,而在 C 中调用相同例程时它可以工作。例如 FindContours 和 cvFindContours

      3. C 与嵌入式设备的兼容性要好得多。但是,我还没有在这个领域做过任何事情。

      【讨论】:

        【解决方案7】:

        我在 IOS 设备上遇到过类似问题,讨论 Maximum speed from IOS/iPad/iPhone 也包含一些适用于其他移动平台的提示。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-02-22
          • 1970-01-01
          • 2016-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多