10

私のクラスでは、課題があり、質問の 1 つに次のように記載されています。

C でのメモリの断片化: 次のことを行う C プログラムを設計、実装、および実行します。それぞれのサイズが 500000 要素の 3m 配列のシーケンスにメモリを割り当てました。次に、すべての偶数番号の配列の割り当てを解除し、それぞれ 700000 要素のサイズの一連の m 個の配列を割り当てます。プログラムが最初のシーケンスと 2 番目のシーケンスの割り当てに必要な時間を測定します。プログラムで使用できるメイン メモリをすべて使い果たすように、m を選択します。タイミングを説明する

これの私の実装は次のとおりです。

#include <iostream>
#include <time.h>
#include <algorithm>

void main(){
    clock_t begin1, stop1, begin2, stop2;
    double tdif = 0, tdif2 = 0;
    for(int k=0;k<1000;k++){
    double dif, dif2;
    const int m = 50000;
    begin1 = clock();
    printf("Step One\n");
    int *container[3*m];
    for(int i=0;i<(3*m);i++)
    {
        int *tmpAry = (int *)malloc(500000*sizeof(int));
        container[i] = tmpAry;
    }
    stop1 = clock();
    printf("Step Two\n");
    for(int i=0;i<(3*m);i+=2)
    {
    free(container[i]);
    }
    begin2 = clock();
    printf("Step Three\n");
    int *container2[m];
    for(int i=0;i<m;i++)
    {
    int *tmpAry = (int *)malloc(700000*sizeof(int));
    container2[i] = tmpAry;
    }
    stop2 = clock();
    dif = (stop1 - begin1)/1000.00;
    dif2 = (stop2 - begin2)/1000.00;
    tdif+=dif;
    tdif/=2;
    tdif2+=dif2;
    tdif2/=2;
}
printf("To Allocate the first array it took: %.5f\n",tdif);
printf("To Allocate the second array it took: %.5f\n",tdif2);
system("pause");
};

これをいくつかの異なる方法で変更しましたが、最初に 3*m*500000 要素配列にメモリを割り当てると、使用可能なメイン メモリがすべて使用されるという一貫性が見られます。しかし、それらを解放するように指示しても、メモリはOSに解放されないため、m * 700000要素配列を割り当てるときに、ページファイル(スワップメモリ​​)でそれを行うため、実際にはメモリの断片化は表示されません.

上記のコードはこれを 1000 回実行して平均化しますが、かなり時間がかかります。最初のシーケンスの平均には 2.06913 秒、2 番目のシーケンスには 0.67594 秒かかりました。2 番目のシーケンスは、断片化がどのように機能するかを示すのに時間がかかると思われますが、スワップが使用されているため、これは発生しません。これを回避する方法はありますか、それとも私の仮定が間違っていますか?

月曜日に持っているものについて教授に尋ねますが、それまでは何か助けていただければ幸いです.

4

1 に答える 1

2

多くの libc 実装 (glibc が含まれていると思います) は、呼び出し時にメモリを OS に解放しませんが、システムコールfree()なしで次の割り当てで使用できるように保持します。また、最新のページングおよび仮想メモリ戦略の複雑さのために、物理メモリのどこに何かがあるかを確認することはできず、意図的に断片化することはほとんど不可能です (たとえ断片化されていたとしても)。すべての仮想メモリとすべての物理メモリは異なる獣であることを覚えておく必要があります。

(以下は Linux 用に書かれていますが、おそらく Windows と OSX に適用できます)

プログラムが最初の割り当てを行うとき、OS がすべてのページを詰め込むのに十分な物理メモリがあるとします。それらはすべて物理メモリ内で隣り合っているわけではなく、可能な限りどこにでも散らばっています。次に、OSはページテーブルを変更して、メモリ内に散在するページを参照する連続した仮想アドレスのセットを作成します。しかし、ここに問題があります。最初に割り当てたメモリは実際には使用しないため、スワップ アウトの候補として非常に適しています。そのため、次の割り当てを行うときに、メモリが不足している OS は、おそらくこれらのページの一部をスワップ アウトして、新しいページ用のスペースを確保します。このため、実際には、断片化ではなく、ディスク速度と、オペレーティング システムのページング メカニズムの効率を測定しています。

連続する仮想アドレスのセットは、実際には (またはメモリ内でさえ) 物理的に連続することはほとんどないことに注意してください。

于 2012-09-08T04:33:51.823 に答える