編集:
はっきりと私はこれをうまく説明しなかったので、例を使ってもう一度試してみましょう。私は与えられたサイズの「パイプ」を持ち、与えられたオフセットで信号がルーティングされます。パイプは、異なるオフセットの信号でフラグメント化される可能性があり、新しい信号を適合させることが不可能になります。パイプをデフラグするための信号の配置方法を教えてくれるアルゴリズムが必要です。しかし、実際には最小限の数の信号が移動しています!だから例のために..
サイズ16のパイプがあるとします。これには、サイズとオフセットが記述された次の信号があります。
offset 0: A (size of 4; fills slots 0-3)
offset 5: C (size of 2, fills slot 5-6)
offset 8: B (size of 4, fills 8-11)
offset 14: D (size 2, fills 14-15)
Pipe: AAAA_CC_BBBB__DD
この場合、オフセット4および7で1つのスロットを開き、オフセット12-13で2つのスロットを開いています。次に、このパイプにサイズ4の信号を追加するとします。現在、そのための連続したスペースはありませんが、デフラグすると、十分なスペースがあることがわかります。「明白な」ソリューションは、次のようにすべての信号を「上部」でグループ化することです。
offset 0: A (size 4, fills 0-3)
offset 4: B (size 4, fills 4-7)
offset 8: C (size 2, fills 8-9)
offset 10: D (size 2, fills 10-11)
Pipe: AAAABBBBCCDD____
これにより、新しい信号用にスロット12〜15が解放されます。ただし、これを行うために3つの信号(BD)を再配置しました。移動した信号ごとに、コマンドをハードウェアに送信し、重要な時間待機する必要があります。
もっと賢くなれば、別のアプローチがあることに気づくことができました。私はこのように再配置できます:
offset 0: A(size 4, fills 0-3)
offset 8: B(size 4, fills 8-11)
offset 12: C(size 2, fills 12-13)
offset 14: D(size 2, fills 14-15).
Pipe: AAAA____BBBBCCDD
これで、新しい信号をオフセット4〜7に合わせることができます。そして、私は1つの信号を再配置する必要がありました(B)。したがって、ハードウェアコールを節約できます。
このような状況を検出するための適切なアルゴリズムがあるかどうか疑問に思っています。最小数の信号を移動して、信号をパイプに「フィット」できます。頭に浮かぶ近づきはNです!アルゴリズム; これは基本的には、「可能なすべての分布を生成し、それが何回移動したかを計算する」ことを表しています。私はより速いアプローチを求めています。
最悪のケースがあまり恐ろしくならない限り、このアプローチは100%完全である必要はありません。私は主に平均的なケースを最小限に抑えることを目指しています。特定のパイプで255を超える信号が発生することはありません。Nで「逃げる」ことができるかもしれません!それが聞こえるほど悪い。また、各信号のサイズはパイプのサイズと同様に2の累乗であることも知っています。
また、断片化を最小限に抑える信号を配置するためのブリリアントアルゴリズムはありますか?
質問への回答。下記参照。
解答を少し詳しく調べて、読んでいる人にとって最適化がどのように行われるかをよりよく説明したいと思いました。buddyは、元の質問だったので、デフラグの部分をより詳細に概念化して説明するためのより簡単な方法を指摘したかったと説明しています。
私のアプローチについて説明します。これは、わずかに異なる/単純なアプローチですが、「バディ」の概念を効果的に維持しています。私はブロックを事前に計算したり、ラベルを付けたりしていません。これは、実装して維持するにはあまりにも多くの労力です。私にとって、信号がどこに行くかを計算するCPUコストは、実際の信号の配置/削除と比較して非常に簡単です。そのため、ロジックを単純化するための事前計算を行わないことで、小さな線形の量のCPUを失う余裕があります。したがって、プロセスは次のとおりです。
挿入用:
すべての信号は、信号サイズと等しい信号境界に保持されるため、信号は、offest%signalsize = 0のオフセットで開始します。実際のオフセットについては、この境界を維持する間隔を調べて把握します。したがって、信号が16サイズのパイプでサイズ4の場合、間隔0〜4、5〜7、8〜11、12〜15を調べます。
各間隔について、その間隔のすべてのスペースが空いているかどうかを確認します。単純なケースでは、信号のない間隔があり、その間隔で信号を配置します。重要なのは、間隔を順番に見て最初の空き間隔に信号を配置することです。これにより、信号を追加するときに(バディ用語を使用して)可能な最小の「ブロック」を確実に破ります。これは、im3l96によって記述されたバディのアプローチと同等でなければなりません。ブロックの事前計算がない場合を除きます。
間隔が完全に空いていない場合は、デフラグする必要があります。このため、最も未使用のスロットを持つ信号を見つけます。複数の間隔に同じ数の未使用のスロットがある場合は、最初の間隔を選択します。次に、この間隔で最大の信号を見つけ、小さい信号に対して同じ挿入アルゴリズムを再帰的に呼び出します(ただし、最初の信号を挿入するために選択した間隔を何らかの理由で使用不可としてマークする場合を除きます)。これにより、信号が適合する別の場所に信号が移動します。次に、選択した間隔で次に小さい信号を見つけ、すべての信号を移動するまで同じことを行います。2 ^ n-1信号の最悪のケースが移動しました。ここで、Nは潜在的な信号サイズ<=私たちの信号の数です(信号が2の倍数であると仮定すると、N = log2(signalSize))。
ここに例があります。*このメソッドを再帰的に呼び出したときに使用不可としてマークされたスロットを表します(つまり、呼び出し側メソッドがシグナルを配置したかったため、再帰呼び出しがシグナルを配置しようとはしません)
これは、私が思いつくことができる、非常に単純な例であり、それでも完全な複雑さを示しています。注:次の構造は作成が困難ですが、誰かが非常に一生懸命に努力した場合のバディのアプローチから生じる可能性があります。
FFFFFFFF__AA_B__EEEE_HGGCC_DII_J
誰かがサイズ8の信号Zを渡します
オフセット8を選択します。
defragInsert(z、サイズ8)
effective structure: FFFFFFFF__AA_B__EEEE_HGGCC_DII_J
placing signal in interval: __AA_B__
defragInput(A、サイズ2)
effective structure: FFFFFFFF********EEEE_HGGCC_DII_J
place signal in interval (offset 20) _H
defragInput(H、size1)
effective structure: FFFFFFFF********EEEE**GGCC_DII_J
place signal between C & D
defragInput(H、size1)を返します
effective structure: FFFFFFFF********EEEE__GGCCHDII_J
place H at offset 20 now that it's open
defragInput(A、サイズ2)を返す
有効な構造:FFFFFFFF_ _ _B__EEEEAAGGCCHDII_J今すぐBを移動...
defragInput(B、size1)
有効な構造:FFFFFFFF * ** * EEEEAAGGCCHDII_J IとJの間にBを配置
defragInput(B、size1)を返します
有効な構造:FFFFFFFF_ __ _EEEEAAGGCCHDIIBJ追加B
defragInsert(z、サイズ8)を返します
fianl structure: FFFFFFFFzzzzzzzzEEEEAAGGCCHDIIBJ