Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Оптимизация чтения\записи  (Прочитано 6468 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Mayor
Специалист

ru
Offline Offline

« : 04-05-2004 08:24 » 

В целях оптимизации под i386 , мне требуется заставить компилятор автоматически при объявлении структуры задавать смещение некоторых полей кратными 4 или  8 байтам  и также для  массивов требуются  структуры размером кратные  4 или 8 , например :

struct r_elem{
c_elem a1;
unsigned char data1[max_t];
unsigned char data2[max_r];
BYTE flags;
unsigned int size;
}

где c_elem структура произвольного размера в целях оптимизации помещается в начало , max_t max_r могут от версии к версии варьировать , но смещения от начала r_elem до   data1 и data2 должны быть кратны 8 байтам ,смещение flags не имеет значения, смещение size д.б. кратно 4 байтам при этом размер структуры д.б. кратен 8

Как об этом сообщить компилятору ?
Записан

1n c0de we trust
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 05-05-2004 09:38 » 

Широко распространённый в мире C приём: сделать union с двумя полями.  Первое поле твоё, второе -- массив того размера, который нужен для выравнивания следующего поля.

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

Код:
struct my_struct
{
    union
    {
        shord _my_field_1; /* My data field */
        int8_t align_1[8];                /* Alignment 64 bits */
    } _u1;
   
    int my_field_2;                       /* This field is aligned to 64 bits */
};

#define my_field_1 _u1._my_aligned_field
« Последнее редактирование: 25-11-2007 20:08 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
darkelf
Молодой специалист

ua
Offline Offline

« Ответ #2 : 05-05-2004 14:07 » 

Вариант с #pragma
Код:
#pragma pack(push, 4)
struct my_struct
{
    short my_field_1; /* My data field */
    int my_field_2;     /* This field is aligned to 64 bits */
};
#pragma pack(pop)
« Последнее редактирование: 25-11-2007 20:08 от Алексей1153++ » Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 05-05-2004 14:29 » 

По-моему, в данном примере для выравнивания на 8 байт должно быть
Код:
#pragma pack(push,8)

К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.
« Последнее редактирование: 25-11-2007 20:23 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Anonymous
Гость
« Ответ #4 : 06-05-2004 16:40 » 

Цитата: npak

К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.


в gсс v3.2 тоже работает, так что не такая уж нестандартная.
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 06-05-2004 17:37 » 

Цитата: Anonymous
Цитата: npak

К сожалению, это нестандартная фича компилятора от майкрософт.  Если в планах есть перенос на другую операционную систему/другой комилятор, то такой способ задать выравнивание может осложнить жизнь.


в gсс v3.2 тоже работает, так что не такая уж нестандартная.


А у меня не работает.  gcc на эту прагму не ругается, но игнорирует.
В примере с union выравнивается правильно.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 06-05-2004 20:56 » 

В gcc есть свой способ указывать выравнивание для полей структур -- атрибут aligned
Код:
struct my_struct_aligned
{
    short aligned_field_1;
    int aligned_field_2 __attribute__((aligned (8)));   
};

Для примера, вот программа для gcc
Код:
#include <stdio.h>

#pragma pack(push, 8)
struct my_struct_pack
{
    short pack_field_1;
    int pack_field_2;   
};
#pragma pack(pop)

struct my_struct_aligned
{
    short aligned_field_1;
    int aligned_field_2 __attribute__((aligned (8)));   
};

struct my_struct_union
{
    union
    {
        short union_1_field_1; /* My data field */
        char align_1[8];                /* Alignment 64 bits */
    } _u1;
   
    int union_field_2;                       /* This field is aligned to 64 bits */
};

#define union_field_1 _u1.union_1_field_1
int ptr_diff(void * p1, void * p2)
{
    return (char *)p2 - (char *)p1;
}

int main()
{
    struct my_struct_aligned sa;
    struct my_struct_union su;
    struct my_struct_pack sp;

    printf( "pack: %d\n", ptr_diff( &(sp.pack_field_1), &(sp.pack_field_2) ) );
    printf( "aligned: %d\n", ptr_diff( &(sa.aligned_field_1), &(sa.aligned_field_2) ) );
    printf( "union: %d\n", ptr_diff( &(su.union_field_1), &(su.union_field_2) ) );
    return 0;
}

У меня под gcc 3.3 получается такой вывод:
pack: 4
aligned: 8
union: 8

Получается, что gcc игнорирует #pragma pack.  С другой стороны, ms vc обругает gcc-ный атрибут.  Выходит, что использование union -- наиболее переносимый подход из представленных.
« Последнее редактирование: 25-11-2007 20:24 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 06-05-2004 20:56 » 

В gcc есть свой способ указывать выравнивание для полей структур -- атрибут aligned
Код:
struct my_struct_aligned
{
    short aligned_field_1;
    int aligned_field_2 __attribute__((aligned (8)));   
};

Для примера, вот программа для gcc
Код:
#include <stdio.h>

#pragma pack(push, 8)
struct my_struct_pack
{
    short pack_field_1;
    int pack_field_2;   
};
#pragma pack(pop)

struct my_struct_aligned
{
    short aligned_field_1;
    int aligned_field_2 __attribute__((aligned (8)));   
};

struct my_struct_union
{
    union
    {
        short union_1_field_1; /* My data field */
        char align_1[8];                /* Alignment 64 bits */
    } _u1;
   
    int union_field_2;                       /* This field is aligned to 64 bits */
};

#define union_field_1 _u1.union_1_field_1
int ptr_diff(void * p1, void * p2)
{
    return (char *)p2 - (char *)p1;
}

int main()
{
    struct my_struct_aligned sa;
    struct my_struct_union su;
    struct my_struct_pack sp;

    printf( "pack: %d\n", ptr_diff( &(sp.pack_field_1), &(sp.pack_field_2) ) );
    printf( "aligned: %d\n", ptr_diff( &(sa.aligned_field_1), &(sa.aligned_field_2) ) );
    printf( "union: %d\n", ptr_diff( &(su.union_field_1), &(su.union_field_2) ) );
    return 0;
}

У меня под gcc 3.3 получается такой вывод:
pack: 4
aligned: 8
union: 8

Получается, что gcc игнорирует #pragma pack.  С другой стороны, ms vc обругает gcc-ный атрибут.  Выходит, что использование union -- наиболее переносимый подход из представленных.
« Последнее редактирование: 25-11-2007 20:34 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 07-05-2004 06:36 » 

Cамым переносимым методом обычно было #ifdef __WIN32__ ... #else ... #endif
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Mayor
Специалист

ru
Offline Offline

« Ответ #9 : 19-05-2004 02:01 » 

Union можно использовать, когда размер структуры известен заранее ,и это действительно удобно в плане переносимости .

Ища в MSDN aligned я наткнулся на __declspec(align(#)) , описания gcc у меня нет , но судя по смыслу это тоже самое, так что в плане переносимости можно воспользоваться советом RXL .
Кстати в плане совместимости, насколько gcc совместим с lcc-win32 ?

А вот чем заменить pack я не знаю , но пока проблема переносимости не стоит , так что буду использовать в msvc ...
Записан

1n c0de we trust
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #10 : 19-05-2004 10:41 » 

Mayor, ты можешь использовать для выравнивания union макросы

Код:
#define ADJUST_TO_MULTIPLE(n, base) ((((n) + (base) - 1)/(base))*(base))
#define ALIGN_TO_8(n) (ADJUST_TO_MULTIPLE(n, 8))

union {
    struct some_struct _u1_value1;
    unsigned char _u1_align[ALIGN_TO_8(n)];
} u1;

для pack в gcc есть атрибут packed.

Судя по инфе в интернете, lcc нацелен на строгую поддержку ansi c.  В нём, похоже, не поддерживаются расшиения gcc.
« Последнее редактирование: 25-11-2007 20:34 от Алексей1153++ » Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
Mayor
Специалист

ru
Offline Offline

« Ответ #11 : 21-05-2004 01:41 » 

Я думаю вариант с union на произвольных структурах несколько сложноват .
Зато предложенные вами alig% , pack% и #ifdef удовлетворяют всем требованиям и являются кроссплатформенными .

Всем спасибо за помощь , вопрос полностью разрешен Улыбаюсь

P.S. ну чтож попробую заценить через недельку lcc, все равно я с gcc пока не работаю , таким образом обратная совместимость пока  мне не нужна
Записан

1n c0de we trust
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines