3

複数のモジュール間で共有されるデータ バッファー、具体的にはイメージ バッファーを作成しようとしています。これらのモジュールはバッファから読み取るだけで、互いにまったく通信しません。私の難しさは次のとおりです。

1.データサイズが大きい:

イメージごとに 10M を超える、つまり、これらのデータを別のスレッドにコピーすることは望ましくありません

2.記憶が乱暴になりたくない:

新しいデータが(リアルタイムで)継続的に入ってくるため、すべてのモジュールが使用を終了したら、非常に古いデータを削除する必要があります。

ただし、物事をさらに複雑にするために、データを消費するモジュールのペースは異なります。一部はより高速/低速で、一部は結果を得るためにより多くのデータ (複数の画像) を必要とし、一部はより少ない (1 つの画像のみ) 必要があります。

最初の問題を解決するために shared_ptr を使用することを考えていました: ブースト shared_ptr(s) のキューを作成し、各 shared_ptr() がイメージ (char 配列) を指すようにします。次に、これらのポインターのサブセットを別のモジュールに渡します。

私はこのスマート ポインター フィールドの初心者です。この問題の良い解決策は何ですか?

ありがとう。

4

6 に答える 6

3

Boost 共有ポインターは、まさに私が提案しようとしていたものです。はい、ポインター クラスに任せてください。

配列ポインターを格納する場合は、shared_ptr の代わりにboost::shared_arrayを使用することに注意してください。

クラス テンプレートはshared_array、動的に割り当てられた配列へのポインターを格納します。(動的に割り当てられた配列は、C++式で割り当てられます。) 指しているオブジェクトは、それを指しているnew[]最後のオブジェクトが破棄またはリセットされると、確実に削除されます。shared_array

于 2009-10-21T04:43:40.813 に答える
2

バッファが作成されたらすぐに s をモジュールに渡すと仮定するとshared_ptr、それらはうまく適合します。その場合、それらを一元的に保存する必要さえありません。

ただし、ある時点でバッファーを作成し、後で別の時点でのみモジュールがバッファーを要求する場合は、さらに複雑になります。
その場合、どのような動作が必要かを理解する必要があります。
しばらくバッファを保持しますか? または、少なくとも 1 つのモジュールがそれらを使用するまで? それとも新しいデータが来るまで?

コメントの統合:
すべてのリーダー/モジュールがすべての受信データを処理するようにするには、これらに入力キューを与えるだけです。受信データでは、モジュールにshared_ptr/shared_arrayを渡すだけで、新しいバッファーにモジュールが追加され、キューに追加されます。
ただし、キューへのアクセスに関しては、マルチスレッドの問題を処理することを忘れないでください。

于 2009-10-21T04:46:18.843 に答える
1

あなたの要件によると、次の 2 つの原則を使用できると思います。

  • shared_array<char>マルチスレッド同期とメモリ処理を処理します
  • モジュールごとに 1 つのキュー: 各モジュールが独自のペースで画像を処理するため、これが必要です。

次に、画像を取得したらすぐに、.a のヒープに割り当てますshared_array<char>。このポインターは、すべてのキューで複製されます。

各キューは個別に同期を必要としますが、これは従来のコンシューマ/プロデューサーのことですが、特に各キューには 1 つのプロデューサー (イメージを受信するスレッド) と 1 つのコンシューマーしかないため、おそらく (かなり) 簡単にプログラムできます。

例を見てみましょう: 3 つのモジュールを取り上げましょう。

=> receiving image 1
module a: ['1'] -> processing (none)
module b: ['1'] -> processing (none)
module c: ['1'] -> processing (none)

=> modules a, b starts treatment of '1'
module a: [] -> processing '1'
module b: [] -> processing '1'
module c: ['1'] -> processing (none)

=> receiving image 2
module a: ['2'] -> processing '1'
module b: ['2'] -> processing '1'
module c: ['2', '1'] -> processing (none)

=> module a finishes treatment of '1', starts treatment of '2'
module a: [] -> processing '2'
module b: ['2'] -> processing '1'
module c: ['2', '1'] -> processing (none)

=> receiving image 3
module a: ['3'] -> processing '2'
module b: ['3', '2'] -> processing '1'
module c: ['3', '2', '1'] -> processing (none)

=> module c starts treatment of '1', '2' and '3'
module a: ['3'] -> processing '2'
module b: ['3', '2'] -> processing '1'
module c: [] -> processing '1', '2' and '3'

=> module a finishes treatment of '2', starts treatment of '3'
=> module b finishes treatment of '1', starts treatment of '2'
=> module c finishes treatment of '1' and '2', keeps '3' for future batch
module a: [] -> processing '3'
module b: ['3'] -> processing '2'
module c: [] -> processing '3' (waiting)

--> at this point '1' is deleted from memory

各モジュール (スレッド) がそのキューを「プール」に登録すると、これを「簡単」にすることもできます。

シグナリングもお勧めします。コンシューマ スレッドが常にキューをポーリングしているということで、(キューが空の場合) 新しいアイテムが挿入されたことをプロデューサがシグナリングする方が良いと常に思います...

于 2009-10-21T08:03:32.890 に答える
0

1.データサイズが大きい:

画像データをヒープに割り当てられたバッファーに格納することを選択し、処理モジュール間でそれらへのポインターを渡すことは正しいです。

2.記憶が暴走したくない

shared_ptr() を使用している場合、メモリ管理にキューを使用する必要はありません。データへのアクセスが必要な場合は shared_ptr() を作成/受け入れ、完了したら shared_ptr() を削除するようにモジュールを設計します。shared_ptr() の意図は、ポインタへの参照がなくなると、ポインタが所有するヒープ メモリを削除することです。

于 2009-10-21T04:49:06.063 に答える
0

boost::shared_arrayをデータ コンテナーとして使用します (John の提案)。また、モジュールの入力キューとしてboost::circular_bufferを使用します。

boost::circular_buffer< const boost::shared_array<char> > input_queue_;

画像は共有されているため、変更するのではなく、必要に応じて新しいコピーを作成してください。

于 2009-10-21T17:44:07.680 に答える
0

画像をファイルに保存して、posixファイルマッピングを試して画像ごとにメモリにマップできるようにします。マッピング後、マルチプロセス間でも効率的に使用できる共有メモリとして作成できます。

ところで: お使いのシステムは posix ファイル マッピングをサポートしていますか? たとえば、Linux の mmap など。

于 2009-10-21T05:34:55.343 に答える