AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 408055
Accepted
noureddine-as
noureddine-as
Asked: 2017-12-01 11:12:36 +0800 CST2017-12-01 11:12:36 +0800 CST 2017-12-01 11:12:36 +0800 CST

基于 OpenCV 的程序优化嵌入式 linux OS [关闭]

  • 772
关闭。这个问题需要更加集中。它目前不接受答案。

想改进这个问题?更新问题,使其仅通过编辑此帖子专注于一个问题。

4年前关闭。

改进这个问题

我正在使用 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;
}

在 i7 PC 上的执行结果 在此处输入图像描述

Raspberry PI 上的执行结果(从 Buildroot 生成的操作系统) 在此处输入图像描述

如您所见,存在巨大差异。我需要的是优化每一个细节,以便这个示例处理步骤以“接近”实时的方式发生,最长为 15 毫秒。

我的问题是:

  • 如何优化我的操作系统以使其能够处理密集计算应用程序以及如何控制每个部分的优先级?
  • 如何充分利用 RPI3 的 4 核来满足要求?
  • 除了 OpenCV,还有其他可能性吗?
  • 我应该使用 C 而不是 C++ 吗?
  • 您推荐的任何硬件改进?
c embedded
  • 1 1 个回答
  • 533 Views

1 个回答

  • Voted
  1. Best Answer
    Austin Hemmelgarn
    2017-12-01T12:50:25+08:002017-12-01T12:50:25+08:00

    为了:

    如何优化我的操作系统以使其能够处理密集计算应用程序以及如何控制每个部分的优先级?

    对于一般优化,除了常规的东西(例如确保只有在后台运行实际需要的东西)之外,您在操作系统方面无能为力。在最初的 Pi 上,您可以通过 'ing 一个名为 'cofi' 的库来加速memmove()和类似的功能,LD_PRELOAD该库提供这些功能的汇编优化版本,但我不确定它是否对 Pi 3 有帮助。

    对于优先级,这确实是要查看手册页的内容,但是除非您将事情并行化,否则您通常无法做到这一点(在您的情况下,似乎显而易见的解决方案是运行每个步骤,因为它赢得了进程并使用 IPC(可能出于性能原因共享内存)在它们之间移动数据)。

    在您从测试程序中引用的结果的注释中,请特别注意 Pi 上的处理和保存步骤都慢了大约 10 倍,而访问步骤仅慢了大约 5 倍,并且这些数字与粗略估计将 Pi 3 与不到一年的通用 PC 进行比较时的预期。Pi 中的 CPU 几乎可以肯定比你运行 PC 测试的 CPU 慢得多(如果你根本没有并行化事情,那么差距会更大,因为大多数现代 x86 CPU 可以单独运行一个内核满负载比他们在满负载下运行所有​​内核的速度要快得多),这将产生影响。ARM ISA 也与 x86 ISA 显着不同(与 x86 相比,ARM 倾向于每个周期执行更少的操作,但

    我也不知道您使用的是什么相机,但我希望您可以通过降低正在处理的图像的分辨率来获得更好的时间,如果您避免使用,您可能可以减少采集时间压缩格式(并且不使用有损压缩意味着分辨率不会那么重要)。

    如何充分利用 RPI3 的 4 核来满足要求?

    在您自己的代码中进行并行化。您只需要确保在您的内核中启用了 SMP(如果您使用的是 RPi Foundation 的官方配置,则应该启用),然后尝试并行运行。我不确定 OpenCV 在并行化事物本身方面做了多少,但您可能也想看看 OpenMP(它提供了一种相当简单的方法来并行化不相互依赖的循环中的迭代)。

    除了 OpenCV,还有其他可能性吗?

    可能有,但每个人都对 OpenCV 进行了标准化,所以我建议使用它(因为每个人都使用它,所以您将更容易获得实施事物的技术帮助)。

    我应该使用 C 而不是 C++ 吗?

    这取决于你如何使用东西。虽然用 C++ 编写慢代码比 C 容易得多,但用这两种语言编写快速代码并不难。两种语言中的许多优化技术都非常相似(例如,在启动时预先分配所有内容,这样您就不会malloc()在临界区调用,或者避免调用stat())。但是,特别是在 C++ 的情况下,避免std::string像瘟疫一样,它到处调用malloc(),因此速度非常慢(我已经看到从std::stringC 风格的字符串转换在某些情况下将性能提高了 40% 以上)。

    您推荐的任何硬件改进?

    假设您试图保持较低的硬件成本并且空间受限(因此选择了 Raspberry Pi),我真的想不出任何东西。Pi(在它的所有迭代中)使用的 SoC 非常适合该价格范围内的计算机视觉工作。如果您愿意使用更大一些且价格更高的东西,我可能会建议使用 NVIDIA Jetson 板(他们使用 Tegra SoC,它具有集成了 192 个 CUDA 内核的 Quadro 等效 GPU,因此它可能可以运行您的处理工作量更快),但是让 Buildroot 在那里工作比在 Pi 上工作要复杂得多。

    针对评论进行编辑:

    进程级别的并行化与多线程不同,它完全不同(最大的区别在于资源如何共享,默认情况下线程共享所有内容,进程不共享任何内容)。通常,当涉及大量处理时,您(通常)最好使用基于进程的并行化,因为编写高效代码更容易,而不必担心线程安全。

    就选项而言,您提到的两者可能会对系统性能产生重大影响,但它们最终都是吞吐量和延迟之间的权衡。抢占模型控制如何重新安排在内核模式下运行的事物(如系统调用)。有以下三个选项:

    1. 无抢占:这几乎意味着在内核模式下运行的任何东西都不能被中断。它与 SVR4 和 4.4BSD 的行为方式以及大多数其他旧 UNIX 系统的工作方式相匹配。它对吞吐量非常有利,但对延迟非常不利,因此它通常仅用于具有大量 CPU 的大型服务器(更多 CPU 意味着它更有可能运行可以被抢占的东西)。
    2. 自愿抢占:这让内核中的每个函数都可以定义可以重新调度的位置。这是大多数面向桌面的 Linux 发行版使用的设置,因为它在吞吐量和延迟之间提供了良好的平衡。
    3. 完全抢占:这意味着(几乎)内核中的任何代码都可以在(几乎)任何时候被中断。这对于在输入和外部事件方面需要非常低延迟的系统很有用,例如用于实时多媒体工作的系统。吞吐量绝对是可怕的,但你无法击败延迟。

    相比之下,定时器频率更容易解释。如果有其他东西等待运行,它控制某物可以不间断运行的最长时间。较高的值会导致较短的时间段(较低的延迟和较低的吞吐量),较低的值会导致较长的时间段(较高的延迟和较高的吞吐量)。作为一般开始,我建议将抢占模型设置为自愿,并将计时器频率设置为 300 Hz,然后开始尝试首先更改计时器频率(因为这通常会产生更明显的影响)。

    至于 Movidius NCS,它是否值得取决于你需要处理多少数据,因为它会受到 USB 连接的带宽限制(Pi 只有一个 USB 2.0 控制器,所以你不仅限于不到 Movidius 设计带宽的十分之一,您还必须至少与以太网适配器共享总线,这将损害您的延迟和吞吐量)。如果您只以低速率处理 32 位颜色的 1920x1080 单帧,那么它可能是可行的,但如果您需要以全帧速率对同一视频进行流处理,那么您可能会遇到延迟问题。如果您确实选择使用一个,请确保您获得了一个有源集线器(否则您可能会遇到问题,因为它试图汲取比 Pi 所能提供的更多的功率)。

    • 1

相关问题

  • 以 root 用户身份访问文件系统

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    JSON数组使用jq来bash变量

    • 4 个回答
  • Marko Smith

    日期可以为 GMT 时区格式化当前时间吗?[复制]

    • 2 个回答
  • Marko Smith

    bash + 通过 bash 脚本从文件中读取变量和值

    • 4 个回答
  • Marko Smith

    如何复制目录并在同一命令中重命名它?

    • 4 个回答
  • Marko Smith

    ssh 连接。X11 连接因身份验证错误而被拒绝

    • 3 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Marko Smith

    systemctl 命令在 RHEL 6 中不起作用

    • 3 个回答
  • Marko Smith

    rsync 端口 22 和 873 使用

    • 2 个回答
  • Marko Smith

    以 100% 的利用率捕捉 /dev/loop -- 没有可用空间

    • 1 个回答
  • Marko Smith

    jq 打印子对象中所有的键和值

    • 2 个回答
  • Martin Hope
    EHerman JSON数组使用jq来bash变量 2017-12-31 14:50:58 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Drux 日期可以为 GMT 时区格式化当前时间吗?[复制] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC 如何复制目录并在同一命令中重命名它? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve “root”用户的文件权限如何工作? 2017-12-22 02:46:01 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST
  • Martin Hope
    Cbhihe 将默认编辑器更改为 vim for _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey 如何下载软件包而不是使用 apt-get 命令安装它? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao 为什么目录 /home、/usr、/var 等都具有相同的 inode 编号 (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg —list-keys 命令在将私钥导入全新安装后输出 uid [未知] 2017-11-26 18:26:02 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve