2

この構造体が96バイトのRAMを使用する理由がわかりません。

struct cell
{
    bool filled;
    bool isParent;
    short int mat;
    bool cx,cy,cz;
    vect norm;
    struct cell* child[8];
    struct cell* parent;
    cell(float pxx=0, float pyy=0, float pzz=0, float ss=0, cell *par=NULL, bool cxx=0, bool cyy=0, bool czz=0);

    void open_read(string);
};

単語の配置については知っていますが、これは少なくとも64バイトを超えてはいけないと思います...この構造体のインスタンスは何百万もあるので、どうすればメモリフットプリントを最小限に抑えることができますか?私はLinuxを使用していて、vectはvector(3 floats)です。

4

3 に答える 3

1

ポインタについてできることはあまりありません。

ただし、シングルビット列挙子またはビットフィールドのいずれかを使用して、すべてのブール値を1バイトに凝縮することができます。の最大値によってはmat、フラグとその値を2バイトに凝縮できる場合があります。それは大きな節約ではありません。

ツリーが非常に密集していると予想される場合は、子供をプールとして割り当てることで大幅な利益が得られる可能性があります。つまり、struct cell* child8つの子すべての配列であるメモリのブロックを参照する単一のポインタがあります。次に、リーフ以外のすべてのノードが必要以上のメモリを割り当てることを理解した上で、レコードごとに7つのポインタのスペースを節約します。また、ノードが空であることを示すフラグがおそらく必要です。

または、配列のランダムアクセスを犠牲にしたい場合は、子をリストとしてチェーンすることもできます。child次に、1つのポインターと1つのポインターが必要ですsibling。ノードごとに6つのポインターを節約し、プーリングによる無駄をなくします。しかし、それは少し厄介になります。

于 2013-02-04T23:51:24.860 に答える
1

問題は明らかに64ビットシステムでの8バイトポインタです

あなたが本当にメモリフットプリントを最小化しようとしていて、それを達成するために踊る気があるなら、私たちはポインタサイズを減らすことを試みることができます

32ビットポインタに移動することはお勧めしません。4GBのRAMにしかアクセスできないためです。これは、大量のメモリを使用している場合は十分ではない可能性があります。

私はこのややクレイジーなアプローチを提案することができます:

構造体には、通常のヒープの代わりにカスタムアロケータを使用します。カスタムアロケータは、基本的に、この特定の構造体のインスタンスに対して、自分で管理する別のヒープを使用していることを意味します。Windows OSでは、これはHeapCreate()で非常に簡単に実行できます。Linuxでは、次の質問で参照されているようにmmapを使用します:HeapCreate、LinuxのHeapAlloc、Linuxのプライベートアロケータ

この構造体タイプには個別のヒープがあるため、このヒープはこの構造体のインスタンスの割り当てと割り当て解除のみを行います。まったく同じサイズのすべての割り当てを使用するとヒープの断片化がなくなるため、これ自体が1つの大きな最適化です。

さて、トリックのために。すべてのインスタンスはこの個別のヒープ内にあるため、インデックスを付けることができます。割り当てられたポインターを取得し、ヒープ開始ポインターを減算して、構造体サイズで除算するだけです。ヒープ内の最初の構造体はインデックス0を取得し、2番目はインデックス1を取得します。構造体へのポインタではなく、構造体のインデックスを保存します。これらのインデックスはスペース効率がはるかに高く、ポインタに簡単に戻すことができます。

もちろん、このアプローチでは、セル構造体へのポインターのみが最小化されます。汎用ヒープ内の一般的なポインターではありません。構造体のサイズで割るのが危険だと感じる場合(これを行うと、すべての構造体がヒープ内で連続していると想定します)、この手順をスキップするだけで、数ビットしか節約できません。ヒープスタートをサブストラクチャするだけで、多くのスペースを節約できます。

少しやり過ぎですが、それでも楽しいです:)

于 2013-02-05T00:11:02.853 に答える
0

カスタムアロケータを使用するというTalkolの提案は良いものです。構造体にランダムな順序でアクセスし、最適なパフォーマンスを実現することに関心がある場合は、構造体が正確にバイトであり、64バイトの境界に配置されるように作業することをお勧めします。データは、メインメモリから「ライン」と呼ばれる64バイトのチャンクでキャッシュにフェッチされます。CPUは、メインメモリからキャッシュにチャンクをフェッチするのに必要な時間で数十または数百の命令を実行できます。構造体にランダムな順序でアクセスする場合、それらを整列させると、各構造体を読み取るために必要なキャッシュラインは2つではなく1つになります。

データに順次アクセスする場合は、構造を小さくすると効率が向上する可能性があることに注意してください。1つにアクセスするには2つのキャッシュラインをフェッチする必要があり、次にアクセスするには最大で1つをフェッチする必要があるためです。構造体が48バイトを使用する場合、アクセスされる4つの構造体の各グループは3つのキャッシュラインフェッチのみを必要としますが、ランダムアクセスは平均1.5のキャッシュラインフェッチを必要とします。

于 2013-02-05T02:30:39.070 に答える