1

C でデータフロー (パイプとフィルター、ストリーム処理、フローベース) を行うにはどうすればよいですか? UNIXパイプではありません。

最近stream.pyに出会いました。

ストリームは、データフロー プログラミングと簡単な並列化を可能にするパイプライン メカニズムを備えたイテラブルです。

アイデアは、イテラブルを別のイテラブルに変換する関数の出力を取得し、それを別のそのような関数の入力としてプラグインすることです。関数合成を使用して既にこれを行うことができますが、このパッケージは >> 演算子をオーバーロードすることで洗練された表記法を提供します。

この種の機能の単純なバージョンを C で複製したいと考えています。特に、>>関数構成の混乱を避けるために、演算子のオーバーロードが気に入っています。ウィキペディアは、1990 年の Usenet の投稿からこのヒントを指摘しています。

なぜC?マイクロコントローラーや他の高級言語 (Max、Pd*、Python) の C 拡張機能でこれを実行できるようにしたいからです。

* (Max と Pd が特にこの目的のために C で書かれていることを考えると、皮肉なことに – 私は必要最小限のものを探しています)

4

3 に答える 3

2

良い答えではないことはわかっていますが、独自の単純なデータフロー フレームワークを作成する必要があります。

私はプロトタイプの DF サーバーを (私の友人と一緒に) 作成しましたが、これにはまだ実装されていない機能がいくつかあります。メッセージで整数データとトリガー データしか渡すことができず、並列処理をサポートしていません。この作業は省略しました。コンポーネントのプロデューサー ポートには、初期化時に設定されたコンシューマー ポートへの関数ポインターのリストがあり、それを呼び出します (リストが空でない場合)。そのため、イベントが発生すると、コンポーネントはデータフロー グラフのツリーのようなウォークスルーを実行します。整数とトリガーで動作するため、非常に高速です。

また、1 つのコンシューマー ポートと 1 つのプロデューサー ポートを持つ奇妙なコンポーネントを作成しました。これは単にデータを通過させるだけですが、別のスレッドで行います。コンシューマー ルーチンは、データを配置してプロデューサー側スレッドにフラグを設定するだけなので、すぐに終了します。汚いですが、それは私のニーズに合っています。ツリーウォークの長いプロセスを切り離します。

お気づきかもしれませんが、これは、グラフのサイズが問題にならない、迅速なタスクのための低トラフィックの非同期システムです。

残念ながら、あなたの問題は私のものとは多くの点で異なります.1つのデータフローシステムが別のデータフローシステムと異なる可能性があるのと同じように、同期、並列、ストリーム処理ソリューションが必要です。

DFサーバーの最大の問題はディスパッチャーだと思います。同時実行性、衝突、スレッド、優先度...前述のとおり、私は問題をスキップしただけで、解決していません。あなたもそれをスキップする必要があります。また、他の問題もスキップする必要があります。

発車係

同期 DF アーキテクチャの場合、特別な場合を除き、すべてのコンポーネントをサイクルごとに 1 回実行する必要があります。それらには単純な前提条件があります: 入力データが利用可能か? そのため、コンポーネントをスキャンして、データが利用可能な場合は、それらを無料の呼び出し元スレッドに渡す必要があります。それらすべてを処理した後、処理されていない N 個のコンポーネントが残ります。リストを再度処理する必要があります。2 回目の処理の後、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);

書きやすい、読みやすい、その他の希望は?

メッセージ

コンポーネントのポート間で純粋な raw パケットを渡す必要があります。プロデューサーとコンシューマーのポートのポインターのペアを含み、「ディスパッチャー」が使用する処理済みフラグを含むバインディングのリストのみが必要です。

通話の問題

問題は、プロデューサがコンシューマ ポートを呼び出すのではなく、コンポーネントを呼び出す必要があることです。すべてのコンポーネント (クラス) 変数と発火はコンポーネント内にあります。そのため、プロデューサーはコンポーネントの共通エントリ ポイントを直接呼び出してコンシューマーの ID を渡すか、ポートを呼び出して、それが属するコンポーネントの任意のメソッドを呼び出す必要があります。


したがって、いくつかの制限に耐えることができる場合は、先に進んで軽量フレームワークを作成してください。それは良い仕事ですが、小さなコンポーネントを書いて、それらがどれほどスマートに接続されて素晴らしいアプリを構築できるかを見るのは、究極の楽しみです.

さらに質問がある場合は、お気軽にお問い合わせください。ここで「データフロー」キーワードをスキャンすることがよくあります。

おそらく、プログラムのより単純なデータフローのモデルを見つけ出すことができます。

于 2010-06-18T23:32:39.193 に答える
1

これはかっこいいです:http ://code.google.com/p/libconcurrency/

C用の軽量の同時実行ライブラリ。主な制御フローの抽象化として対称コルーチンを備えています。ライブラリはステートスレッドに似ていますが、グリーンスレッドの代わりにコルーチンを使用します。これにより、プロシージャ間の呼び出しが簡素化され、シグナリング用のミューテックスとセマフォが大幅に不要になります。

最終的に、コルーチン呼び出しはカーネルスレッド間で安全に移行できるようになるため、達成可能なスケーラビリティは、意図的にシングルスレッドであるステートスレッドよりもはるかに高くなります。

このライブラリは、ダグラスW.ジョーンズの「最小限のユーザーレベルのスレッドパッケージ」に触発されました。svnトランクの疑似プラットフォーム中立プロービングアルゴリズムは、彼のコードから派生しています。

スタックコピーに基づく、より安全でポータブルなコルーチンの実装もあります。これは、Cのポータブル継続に関するsigfpeのページに触発されました。コピーは、スタックスイッチングよりもポータブルで柔軟性があり、スイッチングと競合するコピーを作成することが研究されています。

于 2010-07-20T00:01:29.630 に答える
1

私はそのような目的のためのライブラリを知りません。私の友人は、実験室の割り当てと同様の機能を実装しました。このようなシステムの主な問題は、パフォーマンスが低いこと (長いパイプラインの関数が小さい場合は非常に悪い) と、スケジューリングを実装する必要がある可能性があることです (デッドロックを検出し、パイプバッファーの過負荷を回避するために優先順位を上げます)。

同様のデータ処理の経験から、エラー処理は非常に面倒です。パイプライン内の関数はコンテキストをほとんど知らないため (意図的に、再利用可能にするため)、適切なエラー メッセージを生成することはできません。インライン エラー処理を実装することもできます - エラーをデータとしてパイプに渡すこともできますが、ストリームではエラーが対応する入力に関連付けることができないため、特に出力で特別な処理が必要になります。

このアプローチの既知のパフォーマンスの問題を考えると、それがマイクロコントローラーにどのように適合するかを想像するのは難しいです. パフォーマンスに関しては、単純な関数に勝るものはありません。データ パイプラインを通るすべてのパスに対して関数を作成できます。

おそらく、ストリームの理論的基盤の 1 つであるため、いくつかのペトリ ネット実装 (シミュレーターまたはコード ジェネレーター)を探すことができます。

于 2010-06-18T15:09:45.457 に答える