一定時間の操作で賢いメモリ管理?


18

固定サイズのブロックを含む2つの基本的なメモリ割り当て操作を実行できるメモリセグメント(必要に応じてファイルのようにサイズが拡大または縮小できる)を考えてみましょう。

  • 1つのブロックの割り当て
  • 使用されなくなった以前に割り当てられたブロックを解放します。

また、要件として、メモリ管理システムは現在割り当てられているブロックを移動することはできません。インデックス/アドレスは変更しないでください。

最も単純なメモリ管理アルゴリズムは、グローバルカウンタ(初期値0)をインクリメントし、その新しい値を次の割り当てのアドレスとして使用します。ただし、割り当てられたブロックがわずかしか残っていない場合、セグメントを短くすることはできません。

より良いアプローチ:カウンターを保持しますが、割り当て解除されたブロックのリスト(一定時間で実行可能)を維持し、空でない限り、新しい割り当てのソースとして使用します。

次は何?メモリセグメントを可能な限り短く保つ、一定の時間の割り当てと割り当て解除の制約があるにもかかわらず、できる賢いことはありますか?

(目標は、現在割り当てられていないブロックを最小のアドレスで追跡することですが、一定の時間では実現できないようです…)


以前に行われた割り当て/割り当て解除によってリストが拡大または縮小する可能性があるため、リストのチェックはもはや一定時間ではありませんか?
シム

@Sim、私はそれがリンクされたリストだと仮定していました、そして、それで操作はなるでしょう、なぜならあなたは常に頭だけで作業するからです。O(N)
svick

あなたの「より良いアプローチ」はすでに最適な量のメモリを使用していると思います。つまり、空きブロックがある場合、追加のメモリは割り当てられません。「賢い」アプローチがそれをどのように改善すると思いますか?割り当て解除後にセグメントを縮小できる可能性が高くなるように、先頭近くに割り当てる必要があるということですか?
-svick

@Sim:申し訳ありませんが、スタックという用語を使用する必要があります(ただし、混乱する可能性があると思いました)、「deallocate」はプッシュであり、「allocate」はポップです、または失敗した場合はカウンタの増分にフォールバックします。両方とも一定の時間です。
ステファンギメネス

リアルタイムの制約はありますか、それとも償却された一定の時間で大丈夫ですか?答えはかなり異なる可能性があります。
ジル 'SO-悪であるのをやめる

回答:


11

固定サイズブロ​​ックでは、説明したのはフリーリストです。これは非常に一般的な手法で、次の点があります。空きブロックのリストは、空きブロック自体に保存されます。Cコードでは、次のようになります。

static void *alloc_ptr = START_OF_BIG_SEGMENT;
static void *free_list_head = NULL;

static void *
allocate(void)
{
    void *x;

    if (free_list_head == NULL) {
        x = alloc_ptr;
        alloc_ptr = (char *)alloc_ptr + SIZE_OF_BLOCK;
    } else {
        x = free_list_head;
        free_list_head = *(void **)free_list_head;
    }
    return x;
}

static void
release(void *x)
{
    *(void **)x = free_list_head;
    free_list_head = x;
}

これは、割り当てられたすべてのブロックが同じサイズであり、そのサイズがポインターのサイズの倍数である限りうまく機能するため、アライメントは維持されます。割り当てと割り当て解除は一定の時間です(つまり、メモリアクセスと基本的な追加と同じくらいの時間です-現代のコンピュータでは、メモリアクセスにはキャッシュミス、さらには仮想メモリ、したがってディスクアクセスが含まれる可能性があるため、「一定時間」かなり大きくなる可能性があります)。メモリのオーバーヘッドはありません(追加のブロックごとのポインターなどはありません。割り当てられたブロックは連続しています)。また、割り当てポインターは、一度に多くのブロックを割り当てなければならなかった場合にのみ所定のポイントに到達します。割り当てはフリーリストの使用を優先するため、割り当てポインターは、現在のポインターの下のスペースがクロックでいっぱいになった場合にのみ増加します。その意味で、 技術。

減少リリース後の割り当てポインタはより複雑になる可能性があります。これは、フリーブロックを予測できない順序で処理するフリーリストに従うことによってのみフリーブロックを確実に識別できるためです。可能な場合に大きなセグメントサイズを小さくすることが重要な場合は、オーバーヘッドを増やして別の手法を使用できます。割り当てられた2つのブロックの間に「穴」を開けます。穴は、メモリ順に二重にリンクされたリストでリンクされています。穴の終了位置を知ることで穴の開始アドレスを特定できるように、穴のデータ形式が必要です。また、穴がメモリのどこで始まるかがわかっている場合は、穴のサイズも必要です。次に、ブロックをリリースすると、次の穴と前の穴とマージする穴を作成し、すべての穴の順序付きリストを再構築します(一定時間内に)。オーバーヘッドは、割り当てられたブロックごとに約2ポインターサイズの単語です。しかし、その価格で、「最終的な穴」の発生、つまり大きなセグメントサイズを小さくする機会を確実に検出できます。

多くの可能なバリエーションがあります。入門書としては、Dynamic Storage Allocation:A Survey and Critical Review by Wilson et al。


4
一定の時間で割り当て解除サイトに最も近い穴をどのように見つけますか?
ラファエル

1
私が説明する2番目の方法では、穴はヘッダー(穴のリストの場合はポインターのペア)であり、ゼロ、1つまたは複数のデータブロック用のスペースがあります。割り当てられた2つのブロックの間には、たとえそれが穴ヘッダーだけで構成されるマイクロ穴であっても、常に穴があります。したがって、最も近い穴を見つけるのは簡単です。それらはスロットの直前と直後です。もちろん、マイクロホールはフリーリスト(割り当ての対象となるホールのリスト)には含まれません。もう1つの表示方法は、すべてのブロックとすべての(非マイクロ)ホールにヘッダーを追加することです(16ビットMs-Dosでの割り当てはそのように機能します)。
トーマスポーリン

4

この答えは、一般的なメモリ管理技術に関するものです。すべてのブロックが同じサイズを持っている(そして整列している)場合について質問する質問を逃した。


知っておくべき基本的な戦略は、ファーストフィット、ネクストフィット、ベストフィット、およびバディシステムです。私が教えたコースのために短い要約を一度書いそれが読めることを望んでいる。私はそこをかなり徹底的な調査に向けています。

実際には、これらの基本的な戦略のさまざまな変更が表示されます。しかし、これらのどれも本当に一定の時間ではありません!限られた量のメモリを使用している間、最悪の場合にはそれが可能だとは思いません。


興味深いことに、これを詳しく読む必要があります。しかし、これらのシステムは、一定ではないサイズの割り当てを特に処理しているようです。これは、私が直面している問題ではありません。
ステファンギメネス

正しい。申し訳ありませんが、私はあなたの質問を速すぎて読みました。
rgrig

O(lgn)

s /最小空きブロック/最小アドレスの空きブロック/
rgrig

2

償却分析、特に動的配列を確認することをお勧めします。操作が実際にすべてのステップで一定時間に行われなくても、長期的にはそうであるように見えます。


2
また、動的配列はメモリの割り当てにどの程度役立ちますか?
svick

同じ種類のアルゴリズムを使用して、連続したセルのチャンクを(デ)割り当てますか?ファイル全体が、より大きなチャンクのリンクリストになります。
-gallais
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.