The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Выравнивание данных (linux, gcc)"
Вариант для распечатки  
Пред. тема | След. тема 
Форум Программирование под UNIX (C/C++)
Изначальное сообщение [ Отслеживать ]

"Выравнивание данных (linux, gcc)"  +/
Сообщение от Crou on 28-Июн-11, 16:17 
Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной структуры данных (может, макрос или хидер).
Ответить | Правка | Cообщить модератору

Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Выравнивание данных (linux, gcc)"  +/
Сообщение от me (??) on 28-Июн-11, 21:37 
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).

минимальный - sizeof(void *)

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

2. "Выравнивание данных (linux, gcc)"  +/
Сообщение от arturpub (??) on 28-Июн-11, 23:00 
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).

pow(2, ceil(log2(sizeof(x)))) вроде же

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

3. "Выравнивание данных (linux, gcc)"  +/
Сообщение от guest email(??) on 29-Июн-11, 09:01 
у gcc есть __alignof__


Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

4. "Выравнивание данных (linux, gcc)"  +/
Сообщение от Crou on 29-Июн-11, 21:59 
Нашёл в /usr/include/bits/wordsize.h константу __WORDSIZE. Правда оно в битах, но тоже подходит.
А sizeof(void*) на других платформах (например arm atmega) корректно работает?

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

5. "Выравнивание данных (linux, gcc)"  +2 +/
Сообщение от arturpub (ok) on 30-Июн-11, 02:27 
> Нашёл в /usr/include/bits/wordsize.h константу __WORDSIZE. Правда оно в битах, но тоже
> подходит.
> А sizeof(void*) на других платформах (например arm atmega) корректно работает?

Корректно.

Слушай, граница выравнивания для разных типов данных и/или на разных платформах разная.
Например для х86:

sizeof(char) == 1, граница 1
sizeof(short) == 2, граница 2
sizeof(int) == 4, граница 4
sizeof(double) == 8, граница 8
sizeof(long double) == 10, граница 16, т.к. особо указано в интеловском мануале
sizeof(long long) == 8, граница 4, т.к. для не-FPU/SSE типов граница всегда <= 4

Невыровненные обращения ведут к:

а) падению производительности (засчет двух чтений вместо одного, ну или трех вместо двух)
б) фолту по невыравненному обращению, если включен таковой флаг в MSW/...

sizeof() структуры вообще может быть 57, и выравнивать ее больше, чем на long double, т.е. 16, не имеет смысла, кроме случаев, когда хочется попасть на границу кеш-линии, но это другая история, причем непереносимая даже внутри одной линейки процессоров.

Ты точно ту проблему решаешь?

Ответить | Правка | ^ к родителю #4 | Наверх | Cообщить модератору

6. "Выравнивание данных (linux, gcc)"  +/
Сообщение от Crou on 30-Июн-11, 15:55 
>[оверквотинг удален]
> sizeof(short) == 2, граница 2
> sizeof(int) == 4, граница 4
> sizeof(double) == 8, граница 8
> sizeof(long double) == 10, граница 16, т.к. особо указано в интеловском мануале
> sizeof(long long) == 8, граница 4, т.к. для не-FPU/SSE типов граница всегда
> <= 4
> Невыровненные обращения ведут к:
> а) падению производительности (засчет двух чтений вместо одного, ну или трех вместо
> двух)
> б) фолту по невыравненному обращению, если включен таковой флаг в MSW/...

Это всё понятно.

> sizeof() структуры вообще может быть 57,

Честно говоря, я не представляю sizeof() структуры == 57, ну разве что "поучить" компилятор с помощью  #pragma pack или align директив. Тогда да, возможно всё. Я это не спора ради, так, мысли вслух.

> и выравнивать ее больше, чем на
> long double, т.е. 16, не имеет смысла, кроме случаев, когда хочется
> попасть на границу кеш-линии, но это другая история, причем непереносимая даже
> внутри одной линейки процессоров.
> Ты точно ту проблему решаешь?

Точно ту. Поясню. Есть шаряная память, в котороу я кладу различные структуры, а также массивы типа unsigned char с переменной длиной. Со структурами всё хорошо, они выровненные, никаких проблем не доставляют. А вот массивы unsigned char нужно ручками выравнивать (т.е. добавлять в конце несколько байт), чтобы в памяти следующие за этим массивом структуры или другие массивы после выполнения mmap() имели корректную адресацию. Ещё нюанс, софтина должна уметь работать на x86, x86_64 и arm. Поэтому и озадачился выравниваниями. (про atmega я спросил для общего развития, к вопросу она не имеет отношения).
В общем, спасибо за совет, буду использовать sizeof(void*).

Ответить | Правка | ^ к родителю #5 | Наверх | Cообщить модератору

7. "Выравнивание данных (linux, gcc)"  +/
Сообщение от arturpub (??) on 30-Июн-11, 16:33 
>> sizeof() структуры вообще может быть 57,

Например struct { char a[56]; char c; }, хотя согласен, пример идиотский.
Для struct { short a[28]; char c; } будет уже 58.
Для struct { int a[14]; char c; } будет 60, ну теперь-то идея понятна...

> В общем, спасибо за совет, буду использовать sizeof(void*).

...нужно в структуре визуально найти самый большой по sizeof'у член и выровнять по его границе. Если решение кажется error-prone, например есть структуры в структурах в структурах, можно использовать это:

union {
    intmax_t i;
    long double ld;
    void *p;
};

Ее sizeof есть максимальная граница выравнивания для ISO C99.

Ответить | Правка | ^ к родителю #6 | Наверх | Cообщить модератору

8. "Выравнивание данных (linux, gcc)"  +/
Сообщение от Crou on 30-Июн-11, 17:51 
> union {
>     intmax_t i;
>     long double ld;
>     void *p;
> };
> Ее sizeof есть максимальная граница выравнивания для ISO C99.

Можно и так, но, думаю, можно обойтись просто sizeof(void*). Главная цель: чтобы при обращении к данным (структурам и массивам) из некоторой области shared memory, отображённой в адресное прастранство процесса, процесс обращался к корректным адресам. Т.е. чтобы в отображённом куске shared memory начала структур и массивов имели корректные адреса. Например, на arm'ах (может не на всех, точно не знаю) запрещено обращаться к нечётным адресам, arm генерит исключение при обращении к нечётным адресам. Может linux и умеет разруливать такие ситуации на arm, но не хотелось бы тратить на это процессорное время. Лучше софтину написать с учётом таких особенностей. Думаю, выравнивание данных до размера, кратного sizeof(void*), достаточно и универсально для всех современных архитектур. По крайней мере, для тех трёх, что я указал выше, точно подойдёт.

Ответить | Правка | ^ к родителю #7 | Наверх | Cообщить модератору

9. "Выравнивание данных (linux, gcc)"  +/
Сообщение от AHAHAC (ok) on 30-Июл-11, 07:28 
>> union {
>>     intmax_t i;
>>     long double ld;
>>     void *p;
>> };
>> Ее sizeof есть максимальная граница выравнивания для ISO C99.
> Можно и так, но, думаю, можно обойтись просто sizeof(void*). Главная цель: чтобы
> при обращении к данным (структурам и массивам) из некоторой области shared
> memory, отображённой в адресное прастранство процесса, процесс обращался к корректным
> адресам.

Расскажите, что такая за программулина, которой нужно обращение к корректным адресам?!

Потом я Вам расскажу, единственное место в современном мире где используется выравнивание.
Нет, оно конечно не единственное, есть и более спец. задачи, но те люди которым это нужно
на сайте для лохов не пишут.


  
    

Ответить | Правка | ^ к родителю #8 | Наверх | Cообщить модератору

10. "Выравнивание данных (linux, gcc)"  +/
Сообщение от f00l email(ok) on 01-Авг-11, 11:08 
> Подскажите, есть ли какой-нибудь стандартный способ определить размерность выравнивания
> данных? Т.е. нужно получить число, которому должен быт кратен размер выровненной
> структуры данных (может, макрос или хидер).

Для выравнивания структуры обычно используют ключевое слово __attribute__
для запаковки структуры с параметром  ((__packed__))
пример:
  struct my_packed_struct __attribute__ ((__packed__))
  {
    char c;  
    short int i;
  };

такая структура занимает 3 байта.

больше информации http://gcc.gnu.org/onlinedocs/gcc-4.0.0/gcc/Type-Attributes....

Ответить | Правка | ^ к родителю #0 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Спонсоры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2022 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру