2

私はメモリプールの実装に取り​​組んでいますが、ポインタの配置について少し混乱しています...

固定サイズのメモリブロックを配布するメモリプールがあり、メモリプールの作成時点でmalloc((size)*(ブロック数))があるとします。割り当てられているのがオブジェクトであり、サイズが演算子のサイズからのものである場合、アライメントは問題になりませんが、サイズが不均一である場合(何らかの理由で100バイトのブロックが必要な場合)、mallocによって指定されたチャンクを分割するとポインタが整列していません。私の質問は、常にブロックをある境界に揃えるべきであり、そうであればどちらですか?

4

2 に答える 2

3

適切なアラインメントは、ほとんどのx86実装で少なくとも(パフォーマンス的に)役立ちます(他のアーキテクチャでは、ある種のアラインメントが実際に必須です)。(callocのように)引数のペア、アイテムのサイズ(バイト単位)、およびアイテムの数を1つだけではなく(mallocのようにバイト単位のサイズ)要求する場合があります。次に、本質的に(ブロックサイズを切り上げることによって)アイテムサイズの2の次に高い累乗に揃えることができます(ただし、16を超える16バイトの倍数に切り替えてください。@ derobertが推奨して説明しているように、永遠に倍増し続けないでください。 -)。このように、呼び出し元がアライメントやパディングなしでNバイトを必要とする場合、呼び出し元は常にそれぞれ1バイトのN個のアイテムを要求できます(callocの場合と同じ理由で;-)。

于 2009-09-11T04:45:38.313 に答える
2

X86は位置合わせなしで動作しますが、データが位置合わせされているとパフォーマンスが向上します。タイプの配置は、通常sizeof(type)で、最大16(バイト)です。

私は念のためにこのばかげたテストプログラムを作成しました(mallocはそれが何をしているのかを知っていると思います)、そしてそれは私のamd64ボックスに16を返します。32ビットモードでコンパイルすると8を返します。

#include <stdlib.h>
#include <stdio.h>

int main() {
    int i;
    unsigned long used_bits = 0, alignment;

    for (i = 0; i < 1000; ++i) {
        used_bits |= (unsigned long)malloc(1);   /* common sizes */
        used_bits |= (unsigned long)malloc(2);   
        used_bits |= (unsigned long)malloc(4);
        used_bits |= (unsigned long)malloc(8);
        used_bits |= (unsigned long)malloc(16);
        used_bits |= (unsigned long)malloc(437); /* random number */
    }

    alignment = 1;
    while (!(used_bits & alignment)) {
        alignment <<= 1;
    }

    printf("Alignment is: %lu\n", alignment);
    return 0;
}
于 2009-09-11T04:29:09.850 に答える