1

如何在 C 中进行数据流(管道和过滤器、流处理、基于流)?而不是 UNIX 管道。

我最近遇到了stream.py

流是具有流水线机制的可迭代对象,可实现数据流编程和轻松并行化。

这个想法是获取一个函数的输出,该函数将一个可迭代对象转换为另一个可迭代对象,并将其插入另一个此类函数的输入。虽然您已经可以使用函数组合来做到这一点,但这个包通过重载 >> 运算符为它提供了一个优雅的符号。

我想在 C 中复制这种功能的简单版本。我特别喜欢>>运算符的重载以避免函数组合混乱。维基百科在 1990 年的一篇 Usenet 帖子中指出了这一提示

为什么选择 C?因为我希望能够在微控制器和其他高级语言(Max、Pd*、Python)的 C 扩展中做到这一点。

*(具有讽刺意味的是,Max 和 Pd 是用 C 语言编写的,专门为此目的——我正在寻找一些准系统)

4

3 回答 3

2

我知道,这不是一个好的答案,但您应该制作自己的简单数据流框架。

我写了一个原型 DF 服务器(和我的一个朋友一起),它有几个未实现的特性:它只能在消息中传递 Integer 和 Trigger 数据,并且它不支持并行性。我刚刚跳过了这项工作:组件的生产者端口有一个指向消费者端口的函数指针列表,这些函数指针在初始化时设置,并且它们调用它(如果列表不为空)。因此,当事件触发时,组件会执行数据流图的树状遍历。当他们使用整数和触发器时,它非常快。

此外,我编写了一个奇怪的组件,它有一个消费者和一个生产者端口,它只是简单地通过数据 - 但在另一个线程中。它的消费者例程很快就完成了,因为它只是放置数据并为生产者端线程设置一个标志。很脏,但它适合我的需要:它分离了 tree-walk 的长过程。

因此,正如您可能认识到的那样,它是用于快速任务的低流量异步系统,其中图形大小无关紧要。

不幸的是,您的问题与我的问题有很多不同,就像一个数据流系统可能与另一个不同一样,您需要一个同步、并行的流处理解决方案。

我认为,DF 服务器中最大的问题是调度程序。并发、冲突、线程、优先级……正如我所说,我只是跳过了问题,没有解决。你也应该跳过它。你也应该跳过其他问题。

调度员

在同步 DF 架构的情况下,所有组件必须每个周期运行一次,特殊情况除外。它们有一个简单的前提条件:输入数据是否可用?因此,如果数据可用,您应该只扫描组件,并将它们传递给空闲的调用者线程。在处理完所有这些之后,您将有 N 个剩余组件,这些组件尚未处理。您应该再次处理该列表。在第二次处理后,您将有 M 剩余。如果 N == M,则循环结束。

如果组件的数量低于 100,我认为某种相同的东西会起作用。

捆绑

是的,最好的绑定方式是可视化编程。在完成编辑器之前,类似配置的代码应该使用 insetad,例如:

 // disclaimer: not actual code
 Component* c1 = new AddComponent();
 Component* c2 = new PrintComponent();
 c2->format = "The result is %d\n";
 bind(c1->result,c2->feed);

它易于编写,可读性强,还有其他愿望吗?

信息

您应该在组件的端口之间传递纯原始数据包。您只需要一个绑定列表,其中包含生产者和消费者端口的指针对,并包含“调度程序”使用的已处理标志。

通话问题

问题是生产者不应该调用消费者端口,而是组件;所有组件(类)变量和触发都在组件中。因此,生产者应该直接调用组件的公共入口点,将消费者的 ID 传递给它,或者它应该调用端口,该端口应该调用它所属的组件的任何方法。


所以,如果你能忍受一些限制,我说,继续写你的精简框架。这是一项很好的任务,但是编写小组件并看看,他们可以多么聪明地连接在一起构建一个伟大的应用程序是最终的乐趣。

如果您还有其他问题,请随时提问,我经常在这里扫描“数据流”关键字。

可能,您可以为您的程序找出一个更简单的数据流模型。

于 2010-06-18T23:32:39.193 回答
1

这很酷:http ://code.google.com/p/libconcurrency/

一个轻量级的 C 并发库,以对称协程为主要控制流抽象。该库类似于 State Threads,但使用协程而不是绿色线程。这简化了程序间调用,并在很大程度上消除了对互斥体和信号量的信号量的需求。

最终,协程调用也将能够在内核线程之间安全地迁移,因此可实现的可扩展性因此远高于故意单线程的状态线程。

这个库的灵感来自 Douglas W. Jones 的“最小用户级线程包”。svn trunk上的伪平台中立探测算法来源于他的代码。

还有一个基于堆栈复制的更安全、更便携的协程实现,其灵感来自 sigfpe 的关于 C 中可移植延续的页面。复制比堆栈切换更便携和灵活,并且正在研究使复制与切换具有竞争力。

于 2010-07-20T00:01:29.630 回答
1

我不知道有任何图书馆为此目的。我的朋友在大学里实施了类似的实验室任务。此类系统的主要问题是性能低下(如果长管道中的功能很小,则非常糟糕)和可能需要实现调度(检测死锁并提高优先级以避免管道缓冲区过载)。

根据我对类似数据处理的经验,错误处理是相当繁重的。由于管道中的函数对上下文知之甚少(有意地,为了可重用性),它们无法产生合理的错误消息。可以实现内联错误处理——将错误作为数据传递到管道中——但这需要在所有地方进行特殊处理,尤其是在输出上,因为流不可能与错误对应的输入相关联。

考虑到该方法的已知性能问题,我很难想象这将如何适合微控制器。在性能方面,没有什么比普通函数更好的了:可以为通过数据管道的每条路径创建一个函数。

可能您可以寻找一些Petri 网实现(模拟器或代码生成器),因为它们是流的理论基础之一。

于 2010-06-18T15:09:45.457 回答