Перейти к содержанию
    

VC2015 и VC2010. Файл вырастает в 3,5раза

это не оптимизация. Можно код исходный?

Оптимизация ;) ....так как с выключением оной там становится ещё страшнее. :smile3046:

Исходный? Я же листинг привёл с включением исходных строк.

 

Не знаю. Надо будет дома на VS2005 проверить. На работе VS2005 уже не ставится на win64 :(((

Проверить дома пока не получается - дома +30 и выше - в такой жаре и комп включать не охота. :05:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

определения типов , входящих в эти строки можно? что то додумывать не хочется

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

определения типов , входящих в эти строки можно? что то додумывать не хочется

struct OscRaw {
  uint chainN;                //кол-во не-NULL указателей chain
  uint nv0, ixf0, nvf0;       //соответственно chain[0].nv, chain[0].ixf и chain[0].fmt[ixf].n на момент защёлкивания Get()
  FILETIME timestamp;         //временная метка последних принятых данных
  char timestampOk;           //!=0 - timestamp валидно
  uint oscsrcNV[OSCSRC_n];    //кол-во векторов по каждому источнику осц. непрерывным участком от самого нового вектора до ближайшего разрыва по данному источнику
  HCOsc *chain[OSC_BRING_N];  //массив блоков данных векторов осц. (каждый имеет заголовок HCOsc)
  TIPCALL OscRaw() { ZeroMemory(this, sizeof(*this)); }
  TIPCALL OscRaw(OscRaw const &src) { ZeroMemory(this, sizeof(*this)); *this = src; }
  TIPCALL ~OscRaw() { Destroy(); }
  void TIPCALL Get();
  void TIPCALL Destroy();
  OscRaw & operator =(OscRaw const &);
};
struct HCOsc {
  long volatile use; //кол-во пользователей данного элемента (кол-во link-ов на него)
  uint volatile nv;  //кол-во векторов в данном элементе
  uint ixf;          //индекс последнего записанного элемента fmt (кол-во_записанных_элементов_fmt - 1)
  struct Format {
    u64 map;         //бит-карта источников осц. для n векторов
    uint n;          //кол-во векторов осц. которые соответствуют карте map
    uint TIPCALL GetVktOffs(uint) const;
  } fmt[64];         //список описателей формата векторов в данном элементе HCOsc
  void TIPCALL Delete() { if (!InterlockedDecrement(&use)) delete this; }
};

А приведённый кусок кода - это участок результата компиляции OscRaw::Get():

void TIPCALL OscRaw::Get()
{
  HCOsc *p, **pb = &chain[0];
...
  if (chainN = n) {
    nv0 = (p = chain[0])->nv;
    nvf0 = p->fmt[ixf0 = p->ixf].n;
  }
  timestamp = ::timestamp;
  timestampOk = ::timestampOk;
  memcpy(oscsrcNV, (void *)&::oscsrcNV[0], sizeof(oscsrcNV));
  LeaveCriticalSection(&csb);
}

Как видите - volatile в данных местах нету.

 

PS: Копирование в промежуточную переменную p = chain[0] это уже я позже добавил. В таком варианте эти лишние чтения указателя уже пропадают.

Т.е. - компилятор почему-то сам не догадывается так сделать (сохранить chain[0] в регистре), но если ему явно указать на это, поместив указатель в отдельную переменную (p), то p он уже оптимизирует в регистр.

По идее - раз массив chain указан без volatile, то значит не имеет side effects, а значит его члены можно перемещать куда угодно и создавать сколько угодно копий.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

if (chainN = n) не компилится, это не член OscRaw

В смысле? Посмотрите на первую строчку объявления OscRaw.

Думаете я листинг сам руками рисовал, чтобы всех в заблуждение ввести? :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

где там n?

"..." ни о чём не говорит? Подумайте. Естественно не относящийся к теме код поскипан.

n вычисляется кодом ранее. Потом заносится в chainN. Могли бы догадаться.

Да и зачем вам оно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

PS: Копирование в промежуточную переменную p = chain[0] это уже я позже добавил. В таком варианте эти лишние чтения указателя уже пропадают.

Т.е. - компилятор почему-то сам не догадывается так сделать (сохранить chain[0] в регистре)

Он не может. У вас там присваивания в поля структуры OscRaw (nv0 и nvf0). Для компилятора это запись в память. Видимо анализ указателей у VC хромает (или выключен), и он считает, что эта запись потенциально может попасть в любой глобальный объект (ч том числе и в те, к которым обращаются через указатель). Поэтому содержимое chain может измениться (с точки зрения компилятора).

но если ему явно указать на это, поместив указатель в отдельную переменную (p), то p он уже оптимизирует в регистр.
тут вы взяли отвественность на себя, явно переместив значение в локальную переменную. Для неё pointer анализ говорит, что она ни с какими указателями не пересекается.

По идее - раз массив chain указан без volatile, то значит не имеет side effects, а значит его члены можно перемещать куда угодно и создавать сколько угодно копий.
Нет. В массив могут записать 'сбоку' (не через указатель на него).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нет. В массив могут записать 'сбоку' (не через указатель на него).

Мне кажется странными если оптимизатор делает такие предположения.

Вставил этот код в IAR, вот что он выдал:

     86              nv0 = chain[0]->nv;
   \   00000004   0x6A41             LDR      R1,[R0, #+36];1-е чтение chain[0]
   \   00000006   0x684A             LDR      R2,[R1, #+4] ;чтение chain[0]->nv
   \   00000008   0x6042             STR      R2,[R0, #+4] ;запись nv0
     87              nvf0 = chain[0]->fmt[ixf0 = chain[0]->ixf].n;
   \   0000000A   0x6889             LDR      R1,[R1, #+8] ;чтение chain[0]->ixf
   \   0000000C   0x6A42             LDR      R2,[R0, #+36];3-е чтение chain[0]
   \   0000000E   0x6081             STR      R1,[R0, #+8] ;запись ixf0
   \   00000010   0xEB02 0x1101      ADD      R1,R2,R1, LSL #+4
   \   00000014   0x6989             LDR      R1,[R1, #+24] ;чтение chain[0]->fmt[ixf0].n
   \   00000016   0x60C1             STR      R1,[R0, #+12] ;запись nvf0

Как видно - IAR так не предполагает: он выкинул 2-е чтение chain[0] из памяти, использовав старое значение в регистре, хоть перед этим и была запись в память.

3-е чтение он правда оставил, хотя мог бы тоже использовать если-б не разрушил его перед тем.

Более того - он и 3-е чтение расположил до записи ixf0, хотя если следовать Вашей логике не должен был этого делать. Так что на возможности затирания записями ему наплевать, так как: side effects - это забота программиста.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Более того - он и 3-е чтение расположил до записи ixf0, хотя если следовать Вашей логике не должен был этого делать. Так что на возможности затирания записями ему наплевать
Он не прав :)

 

, так как: side effects - это забота программиста.
Это не так. Если в программе нет того, что называется undefined behavior, то разница в её поведении на разных уровнях оптимизации - это ошибка компилятора.

 

Другое дело, что оптимизатор в VC всегда не являлся сильным местом компилятора. Нормальный оптимизатор в состоянии разобраться (или предположить, если ему пользователь скажет), могут указатели пересекаться или нет.

Попробуйте собрать программу с опцией 'Full program optimization' (или как она там называется). Ещё можно попробовать сделать поля в nv0 и nvf0 другого размера (была такая опция - ansi alias. Она предполагала, что типизированные указатели на память не могут пересекаться, если они указывают на типы, несовместимые по прямому присваиванию. Не знаю, есть ли оно в VC, но всё может быть)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне кажется, здесь объяснено поведение компилятора https://m.habr.com/post/114117/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это не так. Если в программе нет того, что называется undefined behavior, то разница в её поведении на разных уровнях оптимизации - это ошибка компилятора.

Программа и не ведёт себя по-разному на разных уровнях. Багов нет. Есть неоптимальность.

 

Попробуйте собрать программу с опцией 'Full program optimization' (или как она там называется).

У меня и стоит максимальная оптимизация какая только возможно.

 

PS: Ладно - интерес был скорее академический. Проблем со скоростью/размером нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не не, сливаться не стоит. О restrict точно вспомнили, может попробуете с ним?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...