|
|
|
VC2015 и VC2010. Файл вырастает в 3,5раза |
|
|
|
Aug 1 2018, 08:57
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(DASM @ Jul 31 2018, 22:14) это не оптимизация. Можно код исходный? Оптимизация ....так как с выключением оной там становится ещё страшнее. Исходный? Я же листинг привёл с включением исходных строк. Цитата(jcxz @ Jul 31 2018, 15:07) Не знаю. Надо будет дома на VS2005 проверить. На работе VS2005 уже не ставится на win64 (( Проверить дома пока не получается - дома +30 и выше - в такой жаре и комп включать не охота.
|
|
|
|
|
Aug 1 2018, 09:41
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(DASM @ Aug 1 2018, 12:27) определения типов , входящих в эти строки можно? что то додумывать не хочется Код 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, а значит его члены можно перемещать куда угодно и создавать сколько угодно копий.
|
|
|
|
|
Aug 1 2018, 11:33
|
Гуру
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847
|
Цитата(jcxz @ Aug 1 2018, 12:41) PS: Копирование в промежуточную переменную p = chain[0] это уже я позже добавил. В таком варианте эти лишние чтения указателя уже пропадают. Т.е. - компилятор почему-то сам не догадывается так сделать (сохранить chain[0] в регистре) Он не может. У вас там присваивания в поля структуры OscRaw (nv0 и nvf0). Для компилятора это запись в память. Видимо анализ указателей у VC хромает (или выключен), и он считает, что эта запись потенциально может попасть в любой глобальный объект (ч том числе и в те, к которым обращаются через указатель). Поэтому содержимое chain может измениться (с точки зрения компилятора). Цитата но если ему явно указать на это, поместив указатель в отдельную переменную (p), то p он уже оптимизирует в регистр. тут вы взяли отвественность на себя, явно переместив значение в локальную переменную. Для неё pointer анализ говорит, что она ни с какими указателями не пересекается. Цитата По идее - раз массив chain указан без volatile, то значит не имеет side effects, а значит его члены можно перемещать куда угодно и создавать сколько угодно копий. Нет. В массив могут записать 'сбоку' (не через указатель на него).
|
|
|
|
|
Aug 1 2018, 12:12
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(XVR @ Aug 1 2018, 14:33) Нет. В массив могут записать 'сбоку' (не через указатель на него). Мне кажется странными если оптимизатор делает такие предположения. Вставил этот код в 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 - это забота программиста.
|
|
|
|
|
Aug 1 2018, 15:43
|
Гуру
Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847
|
Цитата(jcxz @ Aug 1 2018, 15:12) Более того - он и 3-е чтение расположил до записи ixf0, хотя если следовать Вашей логике не должен был этого делать. Так что на возможности затирания записями ему наплевать Он не прав Цитата , так как: side effects - это забота программиста. Это не так. Если в программе нет того, что называется undefined behavior, то разница в её поведении на разных уровнях оптимизации - это ошибка компилятора. Другое дело, что оптимизатор в VC всегда не являлся сильным местом компилятора. Нормальный оптимизатор в состоянии разобраться (или предположить, если ему пользователь скажет), могут указатели пересекаться или нет. Попробуйте собрать программу с опцией 'Full program optimization' (или как она там называется). Ещё можно попробовать сделать поля в nv0 и nvf0 другого размера (была такая опция - ansi alias. Она предполагала, что типизированные указатели на память не могут пересекаться, если они указывают на типы, несовместимые по прямому присваиванию. Не знаю, есть ли оно в VC, но всё может быть)
|
|
|
|
|
Aug 1 2018, 16:03
|
Гуру
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713
|
Цитата(XVR @ Aug 1 2018, 18:43) Это не так. Если в программе нет того, что называется undefined behavior, то разница в её поведении на разных уровнях оптимизации - это ошибка компилятора. Программа и не ведёт себя по-разному на разных уровнях. Багов нет. Есть неоптимальность. Цитата(XVR @ Aug 1 2018, 18:43) Попробуйте собрать программу с опцией 'Full program optimization' (или как она там называется). У меня и стоит максимальная оптимизация какая только возможно. PS: Ладно - интерес был скорее академический. Проблем со скоростью/размером нет.
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|