18

我计划在 RTOS 平台上实现一个小型数据采集系统。(在 QNX 或 RT-Linux 系统上。)

据我所知,这些工作是使用 C/C++ 执行的,以充分利用系统。然而,我很想知道并想了解一些有经验的人的意见,然后我盲目地投入到编码行动中,用 Python 编写所有东西是否可行和更明智(从低级仪器接口到闪亮的图形用户界面)。如果不是,则将设计的时间关键部分与“C”混合,或者用 C 编写所有内容,甚至不放置一行 Python 代码。

或者至少使用 Python 包装 C 代码以提供对系统的更轻松访问。

你会建议我以哪种方式工作?如果您指出一些类似的设计案例和进一步的阅读材料,我会很高兴。

谢谢

注 1:之所以强调 QNX,是因为我们已经有一个基于 QNX 4.25 的数据采集系统 ( M300 ) 用于我们的大气测量实验。这是一个专有系统,我们无法访问它的内部。进一步了解 QNX 可能对我们有利,因为 6.4 具有免费的学术许可选项,附带 Python 2.5 和最近的 GCC 版本。我从未测试过 RT-Linux 系统,不知道它在稳定性和效率方面与 QNX 相比如何,但我知道 Python 栖息地和非 Python 工具(如 Google Earth)的所有成员都认为新系统大部分时间都可以在开箱即用的作品上开发。

4

5 回答 5

24

我已经构建了几个全 Python 软实时 (RT) 系统,主要周期时间从 1 毫秒到 1 秒。在此过程中,我学到了一些基本的策略和战术:

  1. 使用线程/多处理从主线程卸载非 RT 工作,其中线程之间的队列是可接受的并且协作线程是可能的(没有抢占式线程!)。

  2. 避免 GIL。这基本上意味着不仅要避免线程,还要尽可能地避免系统调用,尤其是在时间关键的操作期间,除非它们是非阻塞的。

  3. 实用时使用 C 模块。事情(通常)用 C 来得更快!但主要是如果您不必自己编写:除非确实别无选择,否则请留在 Python 中。优化 C 模块性能是一个 PITA,尤其是当跨 Python-C 接口进行翻译成为代码中最昂贵的部分时。

  4. 使用 Python 加速器来加速您的代码。我的第一个 RT Python 项目从 Psyco 中受益匪浅(是的,我已经这样做了一段时间)。我今天仍然使用 Python 2.x 的一个原因是 PyPy: LLVM总是让事情变得更快!

  5. 当需要关键时间时,不要害怕忙等待。使用 time.sleep() 在所需时间“偷偷摸摸”,然后在最后 1-10 毫秒内忙等待。我已经能够通过大约 10 微秒的自定时获得可重复的性能。确保您的 Python 任务以最大操作系统优先级运行。

  6. 麻木的岩石!如果您正在执行“实时”分析或大量统计数据,那么没有办法比使用 Numpy 更快地完成更多工作并使用更少的工作(更少的代码,更少的错误)不是我所知道的任何其他语言,包括 C/C++。如果你的大部分代码由 Numpy 调用组成,你会非常非常快。我等不及要完成到 PyPy 的 Numpy 端口了!

  7. 请注意 Python 进行垃圾收集的方式和时间。监控您的内存使用情况,并在需要时强制 GC。确保在时间关键操作期间显式禁用 GC。我所有的 RT Python 系统都在连续运行,而 Python 喜欢占用内存。仔细的编码可以消除几乎所有的动态内存分配,在这种情况下你可以完全禁用 GC!

  8. 尽量分批进行加工。不要以输入速率处理数据,而是尝试以输出速率处理数据,这通常要慢得多。批量处理还可以更方便地收集更高级别的统计信息。

  9. 我提到过使用 PyPy 吗?嗯,值得一提两次。

使用 Python 进行 RT 开发还有许多其他好处。例如,即使您相当确定您的目标语言不能是 Python,但在 Python 中开发和调试原型,然后将其用作最终系统的模板和测试工具,也可以带来巨大的好处。多年来,我一直在使用 Python 创建系统“硬部分”的快速原型,并创建快速不脏的测试 GUI。我的第一个 RT Python 系统就是这样诞生的:原型 (+Psyco) 足够快,即使测试 GUI 正在运行!

-鲍勃

编辑:忘了提及跨平台的好处:我的代码几乎可以在任何地方运行,a)没有重新编译(或编译器依赖项,或需要交叉编译器),b)几乎没有平台相关的代码(主要用于杂项之类的东西文件处理和串行 I/O)。我可以在 Win7-x86 上开发并在 Linux-ARM(或任何其他 POSIX 操作系统,这些天都有 Python)上部署。PyPy 目前主要是 x86,但 ARM 端口正在以令人难以置信的速度发展。

于 2013-02-21T20:52:00.080 回答
15

我不能代表那里的每一种数据采集设置,但他们中的大多数人将大部分“实时操作”都花在等待数据输入上——至少是我研究过的那些。

然后当数据确实进来时,你需要立即记录事件或响应它,然后再回到等待的游戏中。这通常是数据采集系统中时间最关键的部分。出于这个原因,我通常会说在数据采集的 I/O 部分坚持使用 C,但没有任何特别令人信服的理由不在非时间关键部分使用 Python。

如果你有相当宽松的要求——也许只需要毫秒精度——这会增加在 Python 中做所有事情的权重。就开发时间而言,如果您已经对 Python 感到满意,那么如果您在 Python 中做所有事情并仅在出现瓶颈时进行重构,那么您可能会更快地完成产品。在 Python 中完成大部分工作还可以更轻松地彻底测试您的代码,并且作为一般的经验法则,代码行数会更少,因此出现错误的空间也会更小。

如果您需要专门处理多任务(而不是多线程),Stackless Python也可能是有益的。这就像多线程,但线程(或 Stackless 术语中的 tasklet)不是 OS 级别的线程,而是 Python/应用程序级别的线程,因此在 tasklet 之间切换的开销显着减少。您可以将 Stackless 配置为协作或抢占式多任务。最大的缺点是阻塞 IO 通常会阻塞你的整个 tasklet 集。无论如何,考虑到 QNX 已经是一个实时系统,很难推测 Stackless 是否值得使用。

我的投票是采用尽可能多的 Python 路线——我认为它是低成本和高收益的。如果并且当您确实需要用 C 重写时,您将已经有了可以开始工作的代码。

于 2009-09-10T02:17:38.703 回答
7

一般来说,反对在实时环境中使用高级语言的原因是不确定性——当你运行一个例程时,它可能需要 100us;下次你运行相同的例程时,它可能决定扩展一个哈希表,调用 malloc,然后 malloc 向内核请求更多内存,这可以做任何事情,从立即返回到几毫秒后返回到几秒后返回到错误,没有一个从代码中立即显现(或可控)。而从理论上讲,如果您用 C(甚至更低)编写,您可以证明您的关键路径将“始终”(除非流星撞击)在 X 时间内运行。

于 2009-09-10T02:28:08.667 回答
3

我们的团队在 QNX 上结合多种语言完成了一些工作,并且在这种方法上取得了相当大的成功。使用 python 可以对生产力产生很大的影响,而SWIG和 ctypes 等工具可以非常容易地优化代码和组合来自不同语言的功能。

但是,如果您正在编写任何时间紧迫的内容,那么几乎可以肯定它应该用 c 编写。这样做意味着您可以避免像 GIL(全局解释器锁)这样的解释语言的隐含成本,以及许多小内存分配的争用。这两件事都会对您的应用程序的执行方式产生重大影响。

QNX 上的 python 也往往不是 100% 兼容其他发行版(即/有时缺少模块)。

于 2009-09-10T02:16:02.980 回答
0

一个重要提示:QNX 的 Python 通常仅适用于 x86。

我相信你可以为 ppc 和其他拱门编译它,但这不是开箱即用的。

于 2010-06-01T22:12:53.143 回答