Вопрос свой адресую, даже не к знатокам библиотеки Blitz++, и даже не к
знатокам С++, а скорее к специалистам по компиляторам, а конкретно по g++.
Понадобился мне недавно контейнер для работы с одно и двумерными массивами
нулей и единиц, а если проще то с битовым потоком одной системы связи.
Требования были примерно такие:
1. легкость инициализации контейнера данными;
2. поддержка срезов(slice);
3. поддержка видов(view);
4. низкие накладные расходы на адресацию;
5. приветствовались всякие навороты, вроде поддержки раворачивания выражений и т.п.
Естественно выбор пал на Blitz++, который удовлетворял, казалось (в соответствии
с документацией и интернет публикациями), всем требованиям. И все действительно
было здорово, пока на нем не была реализована одна из частей проекта (декодер
Витерби, если кому интересно). А точнее, пока этот декодер небыл протестирован на
производительность под двумя ОС, Linux и Windows, с компиляторами g++ 4.3.3 и Visual C++ 2008 соответственно. Версия собранная под Linux показала более чем
шести кратный поригрыш, по сравнению с тем же самым кодом собранным под Windows
(естественно на том же самом компьютере). В обоих случаях использовались
одинаковые режимы оптимизации (проверялись -Os, -O2 и -O3 ) WTF !!!
Начали разбираться. Выяснили, что g++ отказывается оптимизировать перегруженный
в Blitz++ для класса Array оператор доступа по индексу, а именно operator(). Тесты
показали что он по производительности уступает даже std::list, не говоря уже о std::vector, std::valarray и тем более сишным массивам. Оператор доступа по индексу
для blitz::Array уступал в производительности своему собрату из std::vector почти в 6 раз.
Далее провели небольшое исследование по сравнению кода генерируемого компилятором Visual C++ 2008 и g++ 4.3.3, для операторов доступа к элементам контейнера по
индексу для контейнеров blitz::Array и std::vector. И вот что получилось.
Как видно из приведенного выше, оптимизатор от студии великолепно справился со
своей задачей и создал почти идентичный код для обоих контейнеров. Чего нельзя
сказать о G++, код для std::vector у него получился вполне приличный, а вот с blitz::Array у него вышла какая-то не реальная хрень. Я не большой знаток AT&T-шного синтаксиса, но помоему творится там какая-то муть.
Посему, хотелось бы услышать мнение общественности.
З.Ы. Форматирование асемблерного дампа так и не осилил, но очень-очень старался, так что звиняйте
_>Как видно из приведенного выше, оптимизатор от студии великолепно справился со _>своей задачей и создал почти идентичный код для обоих контейнеров. Чего нельзя _>сказать о G++, код для std::vector у него получился вполне приличный, а вот с _>blitz::Array у него вышла какая-то не реальная хрень. Я не большой знаток _>AT&T-шного синтаксиса, но помоему творится там какая-то муть.
_>Посему, хотелось бы услышать мнение общественности.
Доброго времени суток. Честно говоря, не очень понятно, что вы хотите услышать? Да, gcc сгенерил неоптимальный (мягко говоря) код для array. Например, он вычисляет адрес ячейки с использованием умножения, что иногда сравнимо по стоимости с записью в память. Ну и плюсом "лишние" вычисления адреса (аналог nop для выравнивания) в данном случае не совсем нужны, поскольку составляют примерно половину тела цикла (за исключением impul) по тактам. Как говорится, старался, но ...
Как это поправить — очевидно, посмотреть, чем отличаются array и vector для gcc. И поправить array таким образом, чтобы соответствовало.
_>Чего нельзя сказать о G++ ...... с _>blitz::Array у него вышла какая-то не реальная хрень.
как раз у gcc никакой хрени нет — он сделал ровно то, что написано в коде.
а написано там следующее:
соответственно, почему ms сделал лучше (потому, что у него длиннее ) :
он просто распознал что stride_[0] = 1, и умножение на единицу выкинул. кстати, там в потрохах blitz можно обнаружить в комментах, что разработчики предвидели возможность подобного (это называется constant propagation, то есть вычисление переменных при компиляции), и немножко пытались помочь компилятору (но не всем это помогло)
кстати, для msvc2005 тоже imul остался.
если прямо так уж необходимо быстрее, предлагаю (одномерный случай) грязный хак исходников blitz (blitz/array-impl.h):
определить в compile-time что _bz_rank (в смысле, сколькимерный массив) и выкинуть лишнее сравнение не в пример проще чем протаскивать единичку через поля класса, поскольку он там один раз присваивается как static const int
_> Я не большой знаток AT&T-шного синтаксиса, но помоему творится там какая-то муть.
ну, умножение-то увидишь
кстати, попробуй для двумерных массивов — разница не такой большой должна быть между vc и gcc
_>Посему, хотелось бы услышать мнение общественности.
а вопрос-то в чем?
Здравствуйте, Antikrot, Вы писали:
A>а вопрос-то в чем?
Да то чот g++ неудалась constant propagation оптимизация я понимаю, а вопрос, собственно, в том, почему такая в общем-то не сложная (imho) оптимизация, таки не удалась g++, который, по слухам, является весьма не плохим оптимизирующим компилятором. Кстати, декодер, переведенный с blitz::Array на std::valarray, под Linux оказался быстрее Windows версии процентов на 10.
З.Ы. Вот думаю, стоит ли отпостится ли по этому поводу в багзиллу gcc.
Здравствуйте, first_slider, Вы писали:
_>Да то чот g++ неудалась constant propagation оптимизация я понимаю, а вопрос, собственно, в том, почему такая в общем-то не сложная (imho) оптимизация,
она тут не такая простая... там "константа" как элемент массива, стало быть наверное (не уверен) цепляются проверки на алиасинг с другими задействованными массивами/указателями, а вот это уже такой геморрой...
_>таки не удалась g++, который, по слухам, является весьма не плохим оптимизирующим компилятором.
хз, надо в логи да исходники смотреть, а у меня даже линуха под руками нет, не то что gcc
Re: Blitz++, G++ и operator()
От:
Аноним
Дата:
13.04.09 10:16
Оценка:
Здравствуйте, first_slider, Вы писали:
_>Как видно из приведенного выше, оптимизатор от студии великолепно справился со _>своей задачей и создал почти идентичный код для обоих контейнеров. Чего нельзя _>сказать о G++, код для std::vector у него получился вполне приличный, а вот с _>blitz::Array у него вышла какая-то не реальная хрень. Я не большой знаток _>AT&T-шного синтаксиса, но помоему творится там какая-то муть.
а код который можно было бы собрать, при наличие blitz у вас есть?
Здравствуйте, first_slider, Вы писали:
_>Посему, хотелось бы услышать мнение общественности.
М-м.. а, собственно, что Вы ожидаете услышать? Иногда gcc выдаёт код хуже, чем выдаёт VS. Но не настолько часто чтобы стоило сильно переживать об этом. Иногда, кстати, наблюдаются и обратные вещи — к примеру, у меня gcc 4.3.2 соптимизировал участок, работающий со статической константной строкой, а студия — нет. gcc обнаружил, что из всей строки реально используются только 3 символа и подставил их значения, несмотря на то, что в коде есть цикл, перебирающий символы из этой строки (пустой перебор, значения потом нигде не используются). В результате в бинарнике, выданном gcc самой строки не было, а в бинарнике от VS строка осталась.
Но это фигня.. вот то, что меня сейчас реально беспокоит — то, что в 2005-й студии компиляция иногда просто тупо виснет на многопроцессорной машине. И по ssh компиляция в 2005-й студии не работает.
Здравствуйте, first_slider, Вы писали:
_>Далее провели небольшое исследование по сравнению кода генерируемого компилятором _>Visual C++ 2008 и g++ 4.3.3, для операторов доступа к элементам контейнера по _>индексу для контейнеров blitz::Array и std::vector. И вот что получилось.
А как насчет boost::array и boost::multi_array?
интересно посмотреть на результаты
Здравствуйте, minorlogic, Вы писали:
M>Очень рекомендую попробовать перескочить на boost::ublas, если есть такая возможность.
Я рассматривал uBlas как одного из претендентов, однако по нескольким несколько соображениям от него отказался:
1. мне совершенно не нужен BLAS, мне нужен только удобный контейнер;
2. синтаксически uBlas это полный ужас, одна только реализация концепции срезов (slice и range) чего стоит;
3. да и выдирать его из boost-а как-то лениво.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, first_slider, Вы писали:
_>>Как видно из приведенного выше, оптимизатор от студии великолепно справился со _>>своей задачей и создал почти идентичный код для обоих контейнеров. Чего нельзя _>>сказать о G++, код для std::vector у него получился вполне приличный, а вот с _>>blitz::Array у него вышла какая-то не реальная хрень. Я не большой знаток _>>AT&T-шного синтаксиса, но помоему творится там какая-то муть.
А>а код который можно было бы собрать, при наличие blitz у вас есть?
Эммм, не очень понял суть вопроса, можно подробнее?
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, first_slider, Вы писали:
_>>Далее провели небольшое исследование по сравнению кода генерируемого компилятором _>>Visual C++ 2008 и g++ 4.3.3, для операторов доступа к элементам контейнера по _>>индексу для контейнеров blitz::Array и std::vector. И вот что получилось.
J>А как насчет boost::array и boost::multi_array? J>интересно посмотреть на результаты
boost::array отвергнут изначально, по причине своей статичности, и даже не рассматривался. boost::multi_array отвергнут как обладатель чудовищного синтаксиса и кривой (неполноценной и неудобной — IMHO) реализации концепций срезов (slice) и видов (view).
Здравствуйте, first_slider, Вы писали:
_>Здравствуйте, minorlogic, Вы писали:
M>>Очень рекомендую попробовать перескочить на boost::ublas, если есть такая возможность.
_>Я рассматривал uBlas как одного из претендентов, однако по нескольким несколько соображениям от него отказался: _>1. мне совершенно не нужен BLAS, мне нужен только удобный контейнер;
Blitz тащит намного больше функциональности и кода чем boost::ublas.
_>2. синтаксически uBlas это полный ужас, одна только реализация концепции срезов (slice и range) чего стоит;
Попробуем сравнить
Огромной разницы не вижу. Плюс есть функции "project" для упрощения синтаксиса.
_>3. да и выдирать его из boost-а как-то лениво.
Это уже вопрос политики и техники, выдирать не выдирать.
Из минусов Blitz, основной это неправильная семантика копирования и владения , например нельзя blitz::Array делать членом класса или помещать в стандартные контейнеры.
Здравствуйте, first_slider, Вы писали:
_>2. синтаксически uBlas это полный ужас, одна только реализация концепции срезов (slice и range) чего стоит;
Приведите пример срезов на том и другом , может я смогу помочь ?
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[3]: Blitz++, G++ и operator()
От:
Аноним
Дата:
14.04.09 12:24
Оценка:
Здравствуйте, first_slider, Вы писали:
_>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, first_slider, Вы писали:
_>>>Как видно из приведенного выше, оптимизатор от студии великолепно справился со _>>>своей задачей и создал почти идентичный код для обоих контейнеров. Чего нельзя _>>>сказать о G++, код для std::vector у него получился вполне приличный, а вот с _>>>blitz::Array у него вышла какая-то не реальная хрень. Я не большой знаток _>>>AT&T-шного синтаксиса, но помоему творится там какая-то муть.
А>>а код который можно было бы собрать, при наличие blitz у вас есть?
_>Эммм, не очень понял суть вопроса, можно подробнее?
имеется ввиду готовый cpp файл, в котором уже есть нужные include, хорошо еще был бы main,
чтобы поместить это в багзилу gcc и разработчики gcc могли бы легко воспроизвести эту проблему
Здравствуйте, first_slider, Вы писали:
_>Здравствуйте, jazzer, Вы писали:
J>>Здравствуйте, first_slider, Вы писали:
_>>>Далее провели небольшое исследование по сравнению кода генерируемого компилятором _>>>Visual C++ 2008 и g++ 4.3.3, для операторов доступа к элементам контейнера по _>>>индексу для контейнеров blitz::Array и std::vector. И вот что получилось.
J>>А как насчет boost::array и boost::multi_array? J>>интересно посмотреть на результаты
_>boost::array отвергнут изначально, по причине своей статичности, и даже не рассматривался. boost::multi_array отвергнут как обладатель чудовищного синтаксиса и кривой (неполноценной и неудобной — IMHO) реализации концепций срезов (slice) и видов (view).
Да я не про Ваш проект (я понятия не имею, что Вам нужно, поэтому далек от раздачи советов), а про оптимизатор.
У Вас же есть уже код, который меряет скорость вектора и блица — вот я и прошу этим же (условно) кодом замерить boost::array и boost::multi_array и выложить результаты.
Чтоб, так сказать, было полноценное сравнение оптимизатора на популярных плюсовых библиотеках.
ПС. а что не так с синтаксисом, срезами и вьюхами?
Вроде, синтаксис стандартный, array[i][j][k]
Я до сих пор столкнулся только с одним неудобством: внутренний тип reference в общем случае — не ссылка, что ломает кое-какой код, но, опять же, это обходится очень легко. Но иначе, наверное, сделать многомерную индексацию и не получится.
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, first_slider, Вы писали:
_>>2. синтаксически uBlas это полный ужас, одна только реализация концепции срезов (slice и range) чего стоит;
M>Приведите пример срезов на том и другом , может я смогу помочь ?