【发布时间】:2017-11-30 16:32:21
【问题描述】:
我正在使用 Buildroot 为 Raspberry PI3 构建自己的嵌入式 Linux 操作系统。该操作系统将用于处理多个应用程序,其中之一基于 OpenCV (v3.3.0) 执行对象检测。
我从 Raspbian Jessy + Python 开始,但结果证明执行一个简单的示例需要很多时间,所以我决定设计自己的 RTOS,具有优化的特性 + C++ 开发而不是 Python。
我认为通过这些优化,RPI 的 4 个内核 + 1GB RAM 将处理此类应用程序。问题是,即使有了这些东西,最简单的计算机视觉程序也需要很多时间。
PC 与 Raspberry PI3 比较
这是我编写的一个简单程序,用于了解程序每个部分的执行时间的数量级。
#include <stdio.h>
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <time.h> /* clock_t, clock, CLOCKS_PER_SEC */
using namespace cv;
using namespace std;
int main()
{
setUseOptimized(true);
clock_t t_access, t_proc, t_save, t_total;
// Access time.
t_access = clock();
Mat img0 = imread("img0.jpg", IMREAD_COLOR);// takes ~90ms
t_access = clock() - t_access;
// Processing time
t_proc = clock();
cvtColor(img0, img0, CV_BGR2GRAY);
blur(img0, img0, Size(9,9));// takes ~18ms
t_proc = clock() - t_proc;
// Saving time
t_save = clock();
imwrite("img1.jpg", img0);
t_save = clock() - t_save;
t_total = t_access + t_proc + t_save;
//printf("CLOCKS_PER_SEC = %d\n\n", CLOCKS_PER_SEC);
printf("(TEST 0) Total execution time\t %d cycles \t= %f ms!\n", t_total,((float)t_total)*1000./CLOCKS_PER_SEC);
printf("---->> Accessing in\t %d cycles \t= %f ms.\n", t_access,((float)t_access)*1000./CLOCKS_PER_SEC);
printf("---->> Processing in\t %d cycles \t= %f ms.\n", t_proc,((float)t_proc)*1000./CLOCKS_PER_SEC);
printf("---->> Saving in\t %d cycles \t= %f ms.\n", t_save,((float)t_save)*1000./CLOCKS_PER_SEC);
return 0;
}
在 Raspberry PI 上的执行结果(从 Buildroot 生成的操作系统)
如您所见,存在巨大差异。我需要优化每一个细节,以便此示例 处理 步骤以“近”实时的方式进行,处理时间最长为 15 毫秒,而不是 44 毫秒。所以这些是我的问题:
- 如何优化我的操作系统以使其能够处理密集计算应用程序以及如何控制每个部分的优先级?
- 如何充分利用 RPI3 的 4 核来满足要求?
- 除了 OpenCV,还有其他可能吗?
- 我应该使用 C 而不是 C++?
- 您有什么推荐的硬件改进吗?
【问题讨论】:
-
我认为你有不切实际的期望。只要考虑一下 i7(如果它是低端的)成本大约比整个 Raspberry 高出一个数量级——这一定是有原因的。 (与电源使用类似)。你还没有具体说明你有哪个 i7,但我敢打赌时钟速度更高,它有更多的缓存,更宽更快的内存接口,更宽的 SIMD 寄存器......做研究,运行一些标准基准......跨度>
-
Looking at
blur代码中的现有优化可以利用 OpenCL(不确定 RPi 上的状态)、OpenVX(不熟悉)或 IPP(可能不在 ARM 上) .如果您可以用它构建 OpenCV,也许 OCL 可能是可行的。使用FilterEngine的回退实现看起来并不并行。因此,也许您可以将 4 个较小的重叠 ROI 与线程并行模糊。但是需要支付一些开销。 -
顺便说一句,当您对这样的功能进行计时时,请在一个循环中进行多次测量。第一次调用某些函数可能会导致一些开销(例如,按需加载库)。
-
您的代码是单线程的,因此不会利用 4 个内核。尝试在一个线程中获取,并立即将图像传递给第二个线程,将下一个图像传递给第三个线程,然后以循环方式传递给第四个线程,那么你的 44ms 可能会变成那个的 1/3 ,即你寻求的 15 毫秒。
-
你可以考虑看看针对 ARM 架构优化的东西:FastCV(至少在高通设备上),或者ComputeLibrary?
标签: c++ opencv raspberry-pi embedded-linux buildroot