2014-02-19 3 views
1

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

int *p = new alignas(64) int; 

, но ни один из моих компиляторов, кажется, не дают p адрес, это кратно 64. Вот как я проверяю:

#include <iostream> 

int main() 
{ 
    int *p = new alignas(64) int; 
    std::cout << long(p) % 64 << '\n'; // should print 0 
} 

я должен делать что-то не так. Но что?

+1

Две вещи: a) поддержка переопределенных типов зависит от реализации, а b) очень педантично, все, что вы проверяете, является ли * преобразованное значение * делимым. Что касается языка, у вас нет понятия «выравнивание указателя», кроме как с помощью новых функций языка выравнивания. Указатели не являются целыми числами, они только конвертируются в и из целых чисел. –

+0

Обратите внимание, что я не проверяю выравнивание указателя (это будет значение '& p'), я проверяю выравнивание того, на что он указывает. Да, я согласен, я проверяю значение указателя, преобразованного в 'long', но есть ли лучший способ проверить, выполняется ли мой запрос выравнивания? – KnowItAllWannabe

+0

Да, новые языковые функции довольно существенны и могут иметь то, что вам нужно, например. [ 'Станд :: align'] (http://en.cppreference.com/w/cpp/memory/align). До C++ 11 просто * не было * стандартного понятия выровненной памяти, поэтому он был добавлен. Раньше вам приходилось использовать платформенные методы. –

ответ

1

Задайте еще 64 байта, чем вам нужно, а затем создайте адрес с выровненным кешем в выделенном пространстве. Уход за освобождением всей выделенной памяти в конце.

+0

Я знаю, что есть другие способы делать то, что я хочу сделать (например, использовать 'std :: aligned_storage' или' std :: align'), но я действительно хотел бы понять, почему мое использование 'alignas' isn Не работаем. – KnowItAllWannabe

+0

alignas работает на простых переменных, а не на новых –

+2

доброта. Я невежественна. Std :: aligned storage выглядит очень красиво. Std :: align делает то, что я предложил, но более аккуратно. –

2

Распределитель называется оператором new для того, чтобы выделить пространство является «предполагается возвращать указатели на хранение, которые соответствующим образом выровнены для объектов любого типа с фундаментальным выравниванием » (§ 3.7.4.1/2; цитата из § 5.3.4/11). alignas(64), вероятно, не является «фундаментальным выравниванием» для вашего компилятора и среды, поэтому функция распределения не должна его уважать.

Обратите внимание, что функция распределения пропускает только объем запрашиваемого пространства; он не имеет представления о том, какое выравнивание запрашивается. Следовательно, он не может скорректировать свой результат для удовлетворения особых потребностей.

Спецификатор типа alignas предназначен для работы со статическими и автоматическими объектами. С такими объектами требуемое выравнивание должно соблюдаться, если оно имеет фундаментальное значение, и в идеальном мире компилятор выдаст сообщение об ошибке, если он не может гарантировать, что расширенное выравнивание будет соблюдаться. (Я не думаю, что это обязано сделать это, однако, как gcc, так и clang производят исполняемые файлы, которые segfault, если запрашивается огромное выравнивание стека.)

+0

Я только что проверил это с g ++ 4.8, и ничто не выравнивается выше 8 байтов (что равно стандартное выравнивание памяти). Поэтому я не вижу полезности этого ключевого слова! На x86 существуют регистры, которые требуют, чтобы память была выровнена на 128 байт (а также 64 в качестве используемого OP), но почему-то это совершенно бесполезно для этой цели. Очень жаль. Я даже пытался против структуры и класса, все в конечном итоге смещены. Если он работает только с типом, который уже правильно выровнен, тогда не нужно было добавлять язык! –

+0

@AlexisWilke: Предназначен для размещения в стеке (автоматически) объектов. (И даже там, он не гарантированно работает, но он должен обеспечивать ошибку времени компиляции, если компилятор не может гарантировать выравнивание.) Все объекты, выделенные с помощью 'new', имеют одинаковое выравнивание (по крайней мере, с функцией распределения по умолчанию). Я попробовал это с gcc 4.8/linux, и он отлично работал с alignas (8192). – rici

+0

А ... это работает. Слишком плохо, что это не так с новым. Думаю, мы все еще привязаны к старой доброй функции memalign(). –

Смежные вопросы