| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > аппаратная проверка выравненных данных |
| Автор: null56 27.3.2014, 13:03 | ||||||
| Всем привет Процессор x86/x86_64 Задачи: 1) понять что такое проверка на выравненные данные 2) понять почему срабатывает проверка в конкретном примере 3) понять почему не срабатывает проверка в другом примере 4) понять зачем вообще эта проверка нужна? то есть был введен флаг в регистре СЛОВА (бит 18) http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D0%B8%D1%81%D1%82%D1%80_%D1%84%D0%BB%D0%B0%D0%B3%D0%BE%D0%B2 И так Вопрос 1: правильно ли я понимаю понятие "проверка на выравнивание"? проверка на выравнивание - это ошибка в том случае, когда идет ДОСТУП к данным в оперативной памяти не по кратному машинному слову адресу (4 - для x86, 8 - для ) или это связано с размером данных и адресом? скажем, если читаем 2 байта, то адрес должен быть кратен 2м, 4 - 4м?
И так пример: компилятор gcc 64 разрядный, поэтому буду использовать опцию -m32, чтобы сделать тесты 32разрядных приложений Для незнающих gnu assembler: вставка 1) сохраняет в стек регистр слова, 2) изменяет в этом значении 18 бит, 3) загружает слово обратно в регистр. Код проверенных в дебагере, ошибок нет 32 бита: сборка с флагом -m32
Результат: "Ошибка шины" Вопрос 2: если я правильно понимаю понятие "проверка на выравнивание", то тогда не понимаю, почему в данном примере идет какая - то проверка? ведь я даже к памяти не обратился? 64 бита (в ассемблерной вставке используется расширенный регистр указателя стека rsp, а так та же суть)
Результат: ошибка добиться не получилось Вопрос 3: как добиться аналогичной x86 ошибки на 64 битах? ну и на конец Вопрос 4: для чего нужна эта проверка? в соседних темах были разговоры о более быстром доступе, размещение в кеше еще чего - то... Но, вопрос именно ЗАЧЕМ нужна проверка? где ее можно использовать? Спасибо всем отклинувшимся за помощь |
| Автор: null56 27.3.2014, 13:32 |
| вопрос 1, наверное можно снять, нашел правила выравнивания тут http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html иными словами, правильнее будет считать, что начальный адрес должен быть кратен размеру данных |
| Автор: null56 1.4.2014, 15:07 |
| bsa, да про исключение я знаю, у нас на blackfin как раз падает всё тут ключевое слово "некоторые процессоры". так вот вопрос: зачем на процах(такие как x86), которые умеют читать по невыровненным адресам, этот флажок? для отладки? чтобы переносить на другие процы что ли? |
| Автор: Alexeis 1.4.2014, 15:36 | ||
Производительность разная. Данные выровненные на границу 4/8ми байт быстрее адресуются, чем выравненные на границу 1го байта. |
| Автор: vinter 3.4.2014, 09:13 |
| null56, посмотри первую часть http://scrutator.me/post/2014/01/30/objects_memory_layout_p1.aspx |
| Автор: null56 4.4.2014, 12:45 | ||
| vinter, спасибо за статью, очень наглядно, хотя урывки я вроде где - то уже читал, вроде бы в мейерсе, про тривиальные классы Alexeis, vinter, а теперь прочитаем внимательнее вопрос... может я его не верно задал?
вы мне сказали верно, "выравнивание - это ... и она для того - то..." но! вопрос связан с назначением 18 бита в слове процессора? по умолчанию он выключен на х86, если включаю, то включается и проверка.... вопрос: зачем надо включать этот флаг??? зачем он вообще присутствует в процессоре данной архитектуры? |
| Автор: k0rvin 4.4.2014, 14:21 | ||
Т.е. работа с массивом char менее эффективна, чем с массивом int? |
| Автор: vinter 4.4.2014, 15:28 |
нельзя этого утверждать, как нельзя утверждать и обратное. Всё нужно измерять. |
| Автор: k0rvin 5.4.2014, 05:56 | ||
Ладно, фиг с ней, с эффективностью. Есть такой код:
Один знакомый сказал, что такой способ представления массива «опасен при кроссплатформенности — у разных аппаратных платформ разные требования к выравниванию. Необходимо принять меры в виде пустого куска между указателями и данными», но безопасного варианта он пока не предоставил. Может вы что подскажете? |
| Автор: vinter 5.4.2014, 08:50 |
| k0rvin, да, твой способ хранения явно не лучший, в плане выравнивания. Во первых тебе нужно http://stackoverflow.com/questions/3839922/aligned-malloc-in-gcc по Size. Потом тебе уже надо ручками подсчитать, где после Size должны располагаться Value* и это будет зависеть от размера указателя на платформе. Псле чего тебе нужно посчитать, опять руками, где можно начать располагать Value. На мой взгляд оно того не стоит |
| Автор: Alexeis 5.4.2014, 11:16 | ||||||
Достаточно посмотреть ассемблерный код. Но на самом деле речь об ином. Когда компилятор вставляет код записи в не выровненные поля то добавляются лишние инструкции. Массив байтов считается выравненным. Даже если поставить режим выравнивания на 8 или 16 байтов, все равно в массиве байты будут идти один за другим. Но тем не менее код записи в char длиннее чем в int размера в регистр.
Могу предположить, что флаг связан с риск архитектурой
|
| Автор: vinter 5.4.2014, 12:40 |
нет не достаточно. Ты измерял выровненный и не выровненный код? Я вот измерял и мне пришлось изрядно потрудиться, чтобы написать код при котором будет хотя бы 5% разница на моём core i7. x86 не является RISC, а то, что там внутри наружу выдавать никто не будет, на мой взгляд |
| Автор: k0rvin 6.4.2014, 09:20 | ||||||
Зачем?
А «2*sizeof(Size)» по-твоему зачем? Впрочем тут все относительно просто, как мне предложили
Но размер массива m не известен в compile-time, поэтому я не могу узнать, сколько он на самом деле займет памяти с учетом выравнивания.
«m*sizeof(Value *)» чем не устраивает? Т.е. собвственно проблема в том, чтобы узнать, какое выравнивание использует текущая среда (компилятор+ОС+железо). |
| Автор: vinter 6.4.2014, 09:59 | ||
затем, что если ты задумался о выравнивании, то нужно чтобы первый объект твоих данных находился по выровненному адресу. В твоём коде этого нет. понятия не имею, но к выравниванию это не имеет никакого отношения. К примеру, Size Равный 5 байт. 2*5 = 10. mallco выделяет память по адресу 3. Значит первый Size находится по адресу 3, второй по адресу 8. Указатель по адресу 13. В результате мы имеем чёрти-что. Понятно? тоже самое. так просто или непонятно как сделать?
я понимаю твою запись как: выделить память под 2 Size, m указателей на Value и m x n объектов типа Value. Если всё так, то я не вижу просто го способа решения этой проблемы - нужно много считать и не ошибиться при этом |
| Автор: k0rvin 6.4.2014, 10:58 | ||||
Т.е. malloc может выдать невыровненный адрес?
По сути в этом и есть вопрос: как кроссплатформенно получить это самое значение выравнивания для расчетов. |
| Автор: vinter 6.4.2014, 11:32 | ||
не знаю, но если есть вопросы по-поводу aligned malloc, то, как-минимум ты не можешь контролировать по какой границе он выравнивает, если выравнивает. А тебе не просто нужно знать выровнен или нет адрес но и по какой границе, т.к. выравнивание твоего Size может не совпадать с тем, что даёт malloc(если он и выравнивает, то по границе кратной размеру указателя, я полагаю).
В C++ есть оператор alignof |
| Автор: k0rvin 6.4.2014, 13:11 |
Интересует чистый Си. |
| Автор: bsa 7.4.2014, 22:43 | ||
|