Как получить блоки с большим выравниванием? - PullRequest
9 голосов
/ 14 января 2012

Чтобы избежать сохранения сложных структур данных, я хочу выделить блоки с довольно большим выравниванием (скажем, несколько килобайт, возможно, мегабайт, всегда степенью двойки).Это позволяет мне замаскировать младшие биты указателя, чтобы легко получить адрес начала блока, на который он указывает.

Я бы хотел метод, гарантирующий выделение такого блока с указанным выравниванием,например.выделить 4096 байтовых блоков с выравниванием 4096 байтов.Чтобы метод работал, выравнивание всегда будет размером блоков, поэтому в долгосрочной перспективе ожидается потеря памяти.

Я использую C ++ (поэтому методы C и C ++ хороши), и любое решение должно быть переносимым на обычные рабочие столы.Если портативного решения не существует, Linux имеет наивысший приоритет.

Мне известно о распределении памяти Win32 с большим выравниванием , но если есть общая библиотека C, которая делает это с одной функциейя бы с радостью воспользовался им.

Справочная информация: Я экспериментирую со структурами Vlist, описанными там (конечная цель - это своего рода интерпретатор Scheme),и в настоящее время я внедряю сборку мусора для этих списков.Мне нужны довольно большие блоки памяти в качестве арен для сборщика мусора.Если я изменю технику GC, мне все еще нужно, чтобы блоки VList имели 32-байтовое выравнивание (я выполняю свои эксперименты на 64-битных машинах).

Ответы [ 3 ]

4 голосов
/ 14 января 2012

Я не знаю о полностью портативном решении.Но _mm_malloc() и _mm_free() кажутся поддерживаемыми ICC, GCC и MSVC .

Это было добавлено как часть поддержки выравниваемой памяти для SSEintrinsics.


В противном случае вы можете реализовать свой собственный довольно легко:

void* my_malloc(size_t bytes,size_t align){

    void *ptr = malloc(bytes + align + sizeof(intptr_t));

    if (ptr == NULL)
        return NULL;

    //  Get aligned return address
    intptr_t *ret = (intptr_t*)((((intptr_t)ptr + sizeof(intptr_t)) & ~(intptr_t)(align - 1)) + align);

    //  Save the free pointer
    ret[-1] = (intptr_t)ptr;

    return ret;
}

void my_free(void *ptr){
    if (ptr == NULL)
        return;

    //  Get the free pointer
    ptr = (void*)(((intptr_t*)ptr)[-1]);

    free(ptr); 
}
1 голос
/ 14 января 2012

эффективное большое выравнивание, которое является переносимым, действительно возможно без использования системных вызовов, и в этом случае вы можете просто создать оболочку вокруг VirtualAlloc и mmap, это даст вам выравнивание на уровне страницы, обычно 64 КБ.

но если вам нужно всего 32 байта, просто скопируйте исходный код из windows crt для выровненного malloc и free, он поддерживается стандартным malloc и должен быть идеально переносимым (еще лучше будет версия glibc). в качестве альтернативы вы можете посмотреть на пользовательский распределитель, например nedmalloc

1 голос
/ 14 января 2012

Строительные блоки Intel Thread имеют кроссплатформенный распределитель памяти с открытым исходным кодом и поддержкой выравнивания.

void* scalable_aligned_malloc(size_t size, size_t alignment);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...