私のプログラム、4つの優先度レベル(4つのdeque
s)でのプロデューサー/コンシューマー(2つのスレッド、各ロールに1つ)の問題を回避する方法を見つけようとしています。
基本的に、コンシューマスレッドは、優先度が中程度のdeque
まで削除するよりも、何もなくなるまで、常に最高優先度deque
から削除します。
飢餓が発生している可能性があります。最大優先度deque
が常に要素でいっぱいであり、コンシューマスレッドがそれらを削除するためにビジーで、優先度の低い要素が取得されない場合はどうなりますか?
ある種のエージングメカニズムを実装して、deque
で要素が時間がかかりすぎていないかどうかを確認するように言われました。そうである場合は、それらを取得し、タイマーをリセットして、優先順位の高いdeque
にプッシュしてください。
いいですね。それで、このタスクを実行できるコントローラスレッドの作成を開始しました。設計中にいくつかの質問が出て、答えが見つかりません。
コントローラースレッドが要素を削除してから優先度の高い両端キューにプッシュするまでの最適なタイムアウトを見つけるにはどうすればよいですか?タイムアウトの期限が切れた要素はいくつ削除されますか(1つが小さすぎます。deque
にタイムアウトの期限が切れたすべての要素がある場合、すべての要素が多すぎる可能性があります)?
[〜#〜] edit [〜#〜]:私はUmNyobeのアプローチを試みました、ここに可能な出力があります(各番号はそのdeque
の要素の数です;左端の番号は最大優先順位deque
、右端の優先度の低いdeque
):
// max prio deque has 3 elements, low prio has 7, others are empty
// first round: remove 4 elements with max prio and one with min prio
3 0 0 7
2 0 0 7
1 0 0 7
0 0 0 7
0 0 0 6
// second round: remove one element with min prio
0 0 0 5
// third round: remove one element with min prio
0 0 0 4
// fourth round: remove one element with min prio
// and so on...
0 0 0 3
0 0 0 2
0 0 0 1
0 0 0 0
接続を優先してプロキシを実装しています。たとえば、YouTubeビデオをロードすると、すぐにプレーヤーが表示されます(私はそれに最大の優先度を与え、ビデオがすぐに表示されるので、最大プリオを使用して4つの要素を削除するためです)。ページの要素の読み込みには時間がかかります(優先度を最小にしたため、prioの低い要素を一度に1つ削除すると、ボタンと画像のプレビューが表示されるまでに時間がかかります)。
多分私は除去の順序を逆にするべきです:Xラウンドごとに、最大プリオで1つ、低プリオで4つを除去します、私は知りません。
編集2:多分私は、deque
に格納されている要素が接続要求であることを指摘しておく必要があったでしょう。したがって、ストリーミングビデオの保留中の接続は最大プリオを持ち、deque
から一度に4つ削除されます。文体要素の保留中の接続には最小プリオがあり、それらは一度に1つ削除されます。
私が言いたいのは、deque
に格納されている要素は、タスク、スレッド、またはその他の独立したジョブではなく、何らかの処理を行うということです。これらは、Webページの構成要素です。したがって、Webページのスタイル要素の優先度を低くすることは問題ありませんが、最大のprio要素がロードされた直後(すぐに?)にロードする必要があります。
あなたが説明したスケジューリングのメカニズムは 固定優先度のプリエンプティブスケジューリング です。
最大優先度キューがalwaysいっぱいである可能性があることがわかっている場合は、あなたが説明したように飢餓のため、間違ったメカニズム。
別のスケジューラを使用することで、飢餓を防ぐことができます。たとえば、優先度の低いキューのアイテムを検討する前に、任意のキュー内の最大f(priority)
アイテムを処理すると言うことができます(これはラウンドロビンスケジューリング)。
f
は線形にすることができます:f(p) = p
。優先度4のアイテムを最大4つ(上)、次に優先度3の最大3つのアイテムを処理します...優先度1の1つを処理します。f
は指数関数にすることができます:f(p) = 2^(p-1)
。優先度4の最大8項目(上)、次に最大3の優先度3、次に最大2の優先度2、...、優先度1の1項目を処理します。このラウンドロビンは、各優先度の予想される実行頻度を使用して測定します。
指数関数的な場合を考えて、各キューで待機しているタスクがたくさんあると仮定しましょう。上位8個、上位4個、下位2個、下位1個、上位8個などのスケジュールを設定します。各ラウンドには8 + 4 + 2 + 1 = 15個のタスクがあるため、最優先タスクは消費時間の8/15を占めます、次の4/15、次の2/15、次の1/15。
基本的には、優先順位をpricePaid*A + waitingTime*B
のような2つの変数の関数にします。それは完全に賢明な戦略です。
あなたがチケットを販売していて、人々が支払う価格がそれらをキューの1つに入れると仮定します-高、中、低。これは、優先度が高い、中程度、または低い、単一の順序付けされた優先度キューと見なすことができます。各優先度グループ内では、それらは時間順に並べられているため、負の到着時間をサブ優先度と見なすことができます。これにより、優先度を提供するときに、最も高い優先度の最も古いものが提供されます。それが今あなたがしていることです。優先度は、pricePaid*A + waitingTime*B
のような2つの変数の関数です。ここで、A
は非常に大きいか、またはB
は非常に小さいため、waitingTime
は補償できません。他の誰かがより高い価格を支払った。
私が言っているのは、A
をそれほど大きくしたり、B
をそれほど小さくしたりしないことです。そのためには、データ構造を選択して、誰かからデータ構造を削除するときに、常に最も優先度の高いものを選択するようにします。
それを見る別の方法:到着時刻順に並べられた単一の優先度キューを用意します。ただし、pricePaid
の各増分は、少し前に到着したことと同じです。誰かが$ 20を支払う場合と同様に、$ 10しか支払っていない場合と同じですが、1週間早く到着しました。そうすれば、10ドルしか支払わなかったがtwo週間前に到着した人が最初にサービスを受けることになります。
最初に理解することは、あなたが説明する状況(一部のアイテムは「処理されない」)は、リクエストの量を処理する能力がない場合にのみ発生するということです。特定の期間に予想される量の要求を処理する能力がある場合は、すべての要求を処理できます。これはトートロジーです。リクエストの順序を変更しても、容量やボリュームは変更されません(処理される順序が何らかの理由で処理を変更しない限り)。
それを除けば、忙しい時間帯があり、優先度の低いトランザクションの待ち時間が長すぎる場合があります。その場合は、モデルが正しくありません。現在のアプローチの構造が正しいのは、最も優先度の高いアイテムが常に他のアイテムよりも本当に優先度が高い場合のみです。より高い priority アイテムは、何があっても、最初に低い優先度のアイテムより上で処理されます。ここで言っているのは、優先度の高いアイテムが古い場合、優先度の高いアイテムよりも先に処理したいということです。これは、おそらくSLAに基づいて優先順位付けを構築する必要があることを意味します。つまり、各トランザクションには予想される応答時間があります。次に、期日に基づいてトランザクションを処理します。現在の優先度レベルが高いと、SLAが短くなり、優先度が低いほど、予想される応答時間が長くなります。