Лингвофорум

Лингвоблоги => Личные блоги => Блоги => Алексей Гринь => Тема начата: Алексей Гринь от июля 8, 2009, 11:12

Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 8, 2009, 11:12
Кто-нибудь, объясните.

Есть у меня цикл. Думаю, как бы его заставить быстрее работать.
Вижу, что в одной из функции есть такая строка
if(!key)
                throw NullException(1);

По логике она там не шибко нужна (вызывающая функция уже проверила объект на нуль), я её удаляю (цикл у меня большой и любое действие, вплоть до простого приравнивания к нулю, имеет большие последствия).
И самый прикол, что после удаления мой цикл стал отрабатывать ещё медленнее (!) на 40 мс. Возвращую строку на место - цикл снова ускоряется ровно на 40 мс. При чём с тем же сталкивался я при обнулении объектов (там вплоть до 200 мс). Если их обнулять, то скорость без внятных причин поднимается, хотя
1) обнуление это лишний запись в память
2) логически оно мне это не надо.

Ничо не понимаю. Компилер g++, меряю через GetTickCount. Что не так?
Может быть, с отсутствием кода gcc выравниваниет некоторые места через nop'ы, и, типа, процессор простаивает? Не втыкаю ваще :( Кто здесь мудрит: я, процессор или компилер?
Название: Что за чушь (g++)
Отправлено: RawonaM от июля 8, 2009, 11:22
А ексепшн все-таки хоть раз бросается или нет?
Попробуй if (!key) return; и замерь время.
Название: Что за чушь (g++)
Отправлено: jvarg от июля 8, 2009, 11:26
Скорей всего, компилятор, в случае программного отсутствия проверки исключений, сам подставляет в код таковую. Поройтесь в настройках компилятора, обычно там такие вещи настраиваются.
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 8, 2009, 11:31
Цитата: RawonaM от июля  8, 2009, 11:22
А ексепшн все-таки хоть раз бросается или нет?
Не выкидываются. Если бы выкидывались — я бы видел сообщение о внезапном завершении, потому что они нигде не ловятся.
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 11:43
А свой код можете выложить где-нибудь? Боюсь, без конкретного примера шансы выяснить причину замедления стремятся к нулю.
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 8, 2009, 12:12
Цитата: Gerbarius от июля  8, 2009, 11:43
А свой код можете выложить где-нибудь? Боюсь, без конкретного примера шансы выяснить причину замедления стремятся к нулю.
Да там ничего такого серьёзного.

Цитировать
template <class K, class V>
typename Map<K, V>::Node* Map<K, V>::add(K key, V value)
        {
            if(!key)
                throw NullException(1);


            if(pageCount == 0)
            {
                firstPage = lastPage = new Page();
                pageCount++;
                lastPageRatio = 0;
            }
            else if(lastPageRatio >= NEDO2_CORE_MAP_PAGE_SIZE)
            {
                Page* newPage = new Page();

                lastPage->next = newPage;
                lastPage = newPage;

                pageCount++;
                lastPageRatio = 0;
            }

            Node* node = &(lastPage->nodes[lastPageRatio++]);
                node->key = key;
                node->hash = key->hash();
                node->value = value;

            itemCount++;

            return node;
        }

Этот кусок ну совершенно никак не влияет на логику... Тест сделан так, что key никогда не бывает нулём. Да даже если и будет - вылетит эксепшн и программа закончится с сообщением а ля "This application has requested the Runtime to terminate it in an unusual way" etc. Но такого нетути.

Ничо не понимаю.
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 12:28
Я так понимаю, что key - это объект какого-то класса на самом деле? В таком случае стоит глянуть, что для него делает оператор !. Там нет случайно никаких побочных эффектов?
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 8, 2009, 12:34
Цитата: Gerbarius от июля  8, 2009, 12:28
В таком случае стоит глянуть, что для него делает оператор !
В тесте шаблонная переменная K параметризирована указателем на класс, т.е. действует логика указателя (отрицание адреса в ОЗУ). Да у того класса и operator! не перегружен вовсе.

то бишь там core::Map<core::String*, int> map;
Название: Что за чушь (g++)
Отправлено: jvarg от июля 8, 2009, 12:42
При стандартных настройках проверка деления на нуль всегда неявно вставляется, скажем, при любых опреациях деления.

Какие-то компиляторы позволяют отключать такие приколы, какие-то - нет.
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 13:03
Откуда там указатель?
Почему тогда там написано
Цитировать
template <class K, class V>
typename Map<K, V>::Node* Map<K, V>::add(K key, V value)
а не
Цитировать
template <class K, class V>
typename Map<K, V>::Node* Map<K, V>::add(K *key, V value)
?
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 8, 2009, 13:13
Вместо K подставляется String*
ЦитироватьMap<String*, int> map;

В итоге вызов функции будет такой:
Цитироватьadd(String* key, int value);

Дело в том, что я не так шарю в С++, я всё больше ANSI C или Objective-C пользую. Но тут вот надо. Могу ошибаться в выборе интерфейса. Может быть, так делать не стоит. Не знаю. Язык перему́женный излишне. Его модель ООП и реализация ужасны, давлюсь но полтзуюсь сугубо из сооюражений его мейнстримности.

Чем грозит, если я ставлю так, как есть? Если подставить String или String& разницы или не будет, или не скомпилируется?

P.S. Да, глупость какая-то. Перепишу. :) Потмо сверю скорость. Но что-т не верится, что поможет.
Название: Что за чушь (g++)
Отправлено: Ömer от июля 8, 2009, 13:21
Цитата: Алексей Гринь от июля  8, 2009, 11:12
Может быть, с отсутствием кода gcc выравниваниет некоторые места через nop'ы, и, типа, процессор простаивает? Не втыкаю ваще :( Кто здесь мудрит: я, процессор или компилер?

Так дезасемблируйте и посмотрите, как изменяется код если выкинуть ту строчку.
Название: Что за чушь (g++)
Отправлено: iopq от июля 8, 2009, 13:47
Оптимизация компилятором. Когда проверка на нуль, она проводится ПАРАЛЛЕЛЬНО. Если компилятор сам проверку делает то это он делает сразу перед использованием, т.е. не параллельно.
Название: Что за чушь (g++)
Отправлено: iopq от июля 8, 2009, 13:49
Try this and report:

template <class K, class V>
typename Map<K, V>::Node* Map<K, V>::add(K key, V value)
        {
            if(pageCount == 0)
            {
                firstPage = lastPage = new Page();
                pageCount++;
                lastPageRatio = 0;
            }
            else if(lastPageRatio >= NEDO2_CORE_MAP_PAGE_SIZE)
            {
                Page* newPage = new Page();

                lastPage->next = newPage;
                lastPage = newPage;

                pageCount++;
                lastPageRatio = 0;
            }

            Node* node = &(lastPage->nodes[lastPageRatio++]);
            if(!key)
                throw NullException(1);
                node->key = key;
                node->hash = key->hash();
                node->value = value;

            itemCount++;

            return node;
        }
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 13:54
Угу, надо в ассемблер смотреть (например, можно файл скомпилировать с параметром -s и всеми остальными параметрами как обычно).
Если компилятор не шибко мудрит, то скорее всего в дело вступают всякие процессорные штучки: кэши, предсказания переходов и т.п. Но такие вещи очень трудно исследовать.
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 14:00
Цитата: iopq от июля  8, 2009, 13:47
Если компилятор сам проверку делает
Откуда у всех такая уверенность, что компилятор непременно занимается самодеятельностью? Ему больше заняться нечем? :)
Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 16:44
Цитата: Алексей Гринь от июля  8, 2009, 11:12
Может быть, с отсутствием кода gcc выравниваниет некоторые места через nop'ы, и, типа, процессор простаивает? Не втыкаю ваще :( Кто здесь мудрит: я, процессор или компилер?
А посмотреть ассемблерный код, ты не догадался? :)
Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 16:48
Цитата: jvarg от июля  8, 2009, 12:42
При стандартных настройках проверка деления на нуль всегда неявно вставляется, скажем, при любых опреациях деления.
Вы про какой компилятор говорите?
Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 16:52
Цитата: Алексей Гринь от июля  8, 2009, 11:12
И самый прикол, что после удаления мой цикл стал отрабатывать ещё медленнее (!) на 40 мс.
Тебе прям кровь из носу надо 40 мс сэкономить? :)
Название: Что за чушь (g++)
Отправлено: jvarg от июля 8, 2009, 17:16
Цитата: Gerbarius от июля  8, 2009, 14:00
Цитата: iopq от июля  8, 2009, 13:47
Если компилятор сам проверку делает
Откуда у всех такая уверенность, что компилятор непременно занимается самодеятельностью? Ему больше заняться нечем? :)

Это уверенность от знания общих тенденций создания компиляторов.

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

Если вы пытаетесь делать что-то нестандартное - изменяйте настройки по умолчанию, рассчитанные на большинство.
Название: Что за чушь (g++)
Отправлено: Gerbarius от июля 8, 2009, 17:37
У си/си++ другая идеология. Эти языки позволяют программисту очень многое, но и вся ответственность за качество программы ложится на него. Кстати, gcc не вставляет никаких проверок даже для деления на ноль. Только в том случае, когда ты в коде запишешь деление на ноль как на константу, компилятор выдаст предупреждение, но не ошибку! И уж точно он не проверяет указатели.
Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 17:59
Цитата: jvarg от июля  8, 2009, 17:16
Это уверенность от знания общих тенденций создания компиляторов.
То есть это было чисто умозрительное суждение? :o
Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 18:00
Цитата: Gerbarius от июля  8, 2009, 17:37
Кстати, gcc не вставляет никаких проверок даже для деления на ноль.
И не только gcc. Кстати, gcc ещё довольно предупредителен. :)
Название: Что за чушь (g++)
Отправлено: jvarg от июля 8, 2009, 19:00
Цитировать
Кстати, gcc не вставляет никаких проверок даже для деления на ноль.
Не верю. Это стандартная настройка по умолчанию ЛЮБОГО компилятора, любого языка. Только в некоторых эту опцию отключить нельзя, а в некоторых можно.


Конкретно с gсс я не работал (ибо давно забросил программерство), но во всех предыдущих инкарнациях С++ был в настройках раздел типа "exeption handling", где вся эта фигня настраивалась, и по умолчанию были включены все проверочные подстановки кода... 
Название: Что за чушь (g++)
Отправлено: jvarg от июля 8, 2009, 19:04
Кстати, движок форума не дает мне вставить "g плюс плюс", где вместо "плюс" стоит "+".

Выдает:

Forbidden
You don't have permission to access /index.php on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
________________________________________
Apache/1.3.41 Server at www.lingvoforum.net Port 80

Название: Что за чушь (g++)
Отправлено: myst от июля 8, 2009, 19:18
Цитата: jvarg от июля  8, 2009, 19:00
Не верю. Это стандартная настройка по умолчанию ЛЮБОГО компилятора, любого языка. Только в некоторых эту опцию отключить нельзя, а в некоторых можно.
:o No comments. Зачем верить? Возьмите компилятор и убедитесь сами. VC, например, даже предупреждения не выдаёт, поскольку стандарт не обязывает. Вы стандарт обсуждаемого языка читали? Некоторые компиляторы C++ поддерживают кое-какие проверки, в том числе и во время выполнения, но это абсолютно факультативные вещи, и по умолчанию они естественно выключены.

Цитата: jvarg от июля  8, 2009, 19:00
Конкретно с gсс я не работал (ибо давно забросил программерство), но во всех предыдущих инкарнациях С++ был в настройках раздел типа "exeption handling", где вся эта фигня настраивалась, и по умолчанию были включены все проверочные подстановки кода...
Обработка исключений — это совсем другая история.
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 9, 2009, 05:32
Та-а-ак. Сегодня цифры по скорости другие :) С удалением этого места ускоряется. Хотя ничего не менял в теле цикла. Хе-хе.

Цитата: myst от июля  8, 2009, 16:44
А посмотреть ассемблерный код, ты не догадался?
Ну блин, при работе с Plain C никогда не приходилось. Всё быстро, всё как надо, без всякой самодеятельности. Сказал — сделает. Не сказал — не сделает.

Цитата: myst от июля  8, 2009, 18:00
Кстати, gcc ещё довольно предупредителен
Ага. У меня там возвращается неполный тип (не очень вкуриваю, чем он неполон), и поэтому приходится писать typename Map<K, V>::Node вместо Map<K, V>::Node — g++ ругается (мол, синтаксический парсер не может явно определить, что это тип, а не, скажем, глобальная переменная). А MC++ (2003 года выпуска at least), я слышал, пытается сам определить, что это такое по контексту. Во-первых, не факт, что он определит верно. Во-вторых, такая программа не переносима (т.е. при переносе под gcc будешь долго пытаться вкурить, чо такое случилось). В-третьих, это вроде бы не по стандарту.

Цитата: jvarg от июля  8, 2009, 19:04
Кстати, движок форума не дает мне вставить "g плюс плюс", где вместо "плюс" стоит "+".

Выдает:

Forbidden
You don't have permission to access /index.php on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Ага :( Это всё козни микрософтцев :)
Название: Что за чушь (g++)
Отправлено: myst от июля 9, 2009, 05:39
Чего делаешь-то хоть, расскажи. :)
Название: Что за чушь (g++)
Отправлено: GaLL от июля 9, 2009, 05:42
А сколько итераций в цикле и сколько времени он работает? Если >= секунде, то флуктуации в ~40 мс - обычное дело.
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 9, 2009, 05:58
Цитата: GaLL от июля  9, 2009, 05:42
Если >= секунде, то флуктуации в ~40 мс - обычное дело.
Не, одно дело когда эти флуктуации случайны, по вине Винды, и каждый раз то +40 мс, то -40мс, то +100мс — не определить.
А тут было стойкое правило: удаляешь — умедляется, добавляешь — ускоряется. Каждый раз повторялось. Значит это где-то компилятор что-то без моего ведома вставил...

Цитата: myst от июля  9, 2009, 05:39
Чего делаешь-то хоть, расскажи. :)
Да так... :) Экспериментирую со скоростью алгоритмов... Вчера каждый час выигрывал по 100 мс, по капельке то там, то сям подчищая... А тут — нате.

Чувствую, вообщем, ничего лучше Plain C нету. Он просто идеальнейший по простоте и чистоте язык :) Щас думаю накатать себе диздок для правильной имплементации ООП под ним (костыль, зато надёжный).
Название: Что за чушь (g++)
Отправлено: GaLL от июля 9, 2009, 07:12
Может быть дело в том, что при удалении части кода адреса джампов так же смещаются, а джамп на начало параграфа (т. е. на адрес, кратный 16) часто более эффективен (по крайней мере, это верно для джапмов, образующих циклы; кроме того, не зря же нормальные компиляторы обычно выравниваниют адреса подпрограмм по 16 байт)?
Название: Что за чушь (g++)
Отправлено: jvarg от июля 9, 2009, 08:26
Пошарился сейчас в яндексе. Все-таки, нужно явно отключать скрытые проверки, служебные и отладочные коды при помощи флагов компилятора.

Что-то вроде: "-fno-rtti -fno-exceptions"

Поройтесь в описании флагов.
Название: Что за чушь (g++)
Отправлено: myst от июля 10, 2009, 00:45
Цитата: jvarg от июля  9, 2009, 08:26
Пошарился сейчас в яндексе. Все-таки, нужно явно отключать скрытые проверки, служебные и отладочные коды при помощи флагов компилятора.
Чиво? :o В gcc? Линки — студию!

Цитата: jvarg от июля  9, 2009, 08:26
Что-то вроде: "-fno-rtti -fno-exceptions"
Это не в тему.
Название: Что за чушь (g++)
Отправлено: myst от июля 10, 2009, 00:47
Цитата: GaLL от июля  9, 2009, 07:12
Может быть дело в том, что при удалении части кода адреса джампов так же смещаются, а джамп на начало параграфа (т. е. на адрес, кратный 16) часто более эффективен (по крайней мере, это верно для джапмов, образующих циклы; кроме того, не зря же нормальные компиляторы обычно выравниваниют адреса подпрограмм по 16 байт)?
Да чё гадать? Надо посмотреть ассемблерный выхлоп, и всё станет ясно. Делов-то.
Название: Что за чушь (g++)
Отправлено: myst от июля 10, 2009, 01:29
Цитата: Алексей Гринь от июля  8, 2009, 11:12
GetTickCount
Ты в курсе, что её разрешение зависит от разрешения системного таймера? Какое оно в твоей системе?
Название: Что за чушь (g++)
Отправлено: Алексей Гринь от июля 10, 2009, 02:38
Цитата: myst от июля 10, 2009, 01:29
ЦитироватьGetTickCount
Ты в курсе, что её разрешение зависит от разрешения системного таймера? Какое оно в твоей системе?
Ёпрст. Если тест срабатывает при одном условии при запуске 100 раз *каждый раз* 5600 мс (плюс минут 3 мс), а при других условиях при запуске 100 раз — стабильно 6200 мс (плюсминус 3 мс)— это значит, что таймер тут ни при чём.

P.S. И вообще я тему блокировал, ты как суперадмин не замечаешь этого даже...
Название: Что за чушь (g++)
Отправлено: myst от июля 10, 2009, 03:21
Цитата: Алексей Гринь от июля 10, 2009, 02:38
P.S. И вообще я тему блокировал, ты как суперадмин не замечаешь этого даже...
Упс... :-[