Intel VTune Amplifier XE 2011 beta под строгим взглядом программиста

    Picture 1
    Решил посмотреть на новый Intel VTune Amplifier XE 2011 beta и написать статью о примере использования. Правда, в процессе написания акцент частично сместился от использования Amplifier к его тестированию. Но это тоже хорошо, надеюсь, разработчики в Intel учтут пожелания и внесут изменения в следующую версию инструмента. И вообще буду критиковать и себя, и всех. :)



    Начну немного издалека, иначе возникнут вопросы, зачем мне понадобился код, который мне пришлось оптимизировать. В ходе разработки статического анализатора кода для Си++ мне приходится сталкиваться с весьма экзотическими фрагментами программ. Чего только программисты не придумывают. И даже такие компиляторы, как Visual C++ или Intel C++ нет, нет, да и упадут на очередной «загогулине».

    В нашем статическом анализаторе PVS-Studio есть одно не очень хорошее место, связанное с определением типа объектов. Есть, например, конструкция:
    typedef int A;
    typedef A B;
    B myValue;

    и необходимо «вычислить» тип B, чтобы узнать, что это не что иное, как int. С подобными примерами, конечно, никаких сложностей нет и все работает. Однако бывают очень запутанные ситуации. Приведу пример кода, демонстрирующего откуда начинают появляться разные сложности:
    Picture 2
    При попытке узнать тип переменной X мы посмотрим ее тип в namespace B и не найдем его там. Тогда мы увидим, что надо посмотреть в namespace C. И тоже там не найдем. Теперь надо посмотреть и в namespace B… Вечный цикл. Конечно, это простой случай и с ним тоже никаких проблем нет. Но добавьте сюда typedef, шаблоны, наследуемые классы. Иногда получаются удивительно сложные вещи, причем не специально. Особенно это проявляется в коде с шаблонами.

    К сожалению, инструмент PVS-Studio иногда входил в вечный цикл на особенно «удачных конструкциях» и делал самоубийство через 5 минут, чтобы было возможно продолжить обработку других файлов. Очень редкая ситуация, но неприятная. Ошибки, конечно, правятся и правятся, но находятся все новые ситуации. Причем не всегда есть возможность узнать, что же это за код такой у пользователя. Было принято решение не полностью обрывать работу анализатора по таймеру, а отказаться от получения типа какого-то объекта, если возникает зацикливание. Лучше пропустить одну переменную, чем весь файл.

    Здесь проявляет очень интересный момент несовместимости теории и практики. Теоретически надо написать так, чтобы ошибок не было. Даже пожурить нас можно. Разработчики статического анализатора, писатели статей как писать без ошибок, а сами не могут сделать верный разбор типа переменных. А вот получается, что не можем. И не только мы. Задачи, связанные с компиляцией Си++ кода крайне сложные. И приходится от рассуждений о высоком и прекрасном переходить к созданию заплаток на всякий случай.

    Был создан простой, но эффективный механизм остановки. Если при получении типа объекта мы получаем указатель на закодированный тип, с которым уже работали до этого, то стоп. Для начала был создан просто класс, содержащий множество указателей в std::set<const void*> *m_pGuardPointers. Если в множестве уже есть указатель, то значит пора остановиться.

    Я не удивился, когда производительность программы после такого изменения упала во много раз. Я ожидал подобного эффекта. Не стал даже мерить скорость, и так видно, что очень медленно и причина понятна. Обычно глубина «вывода» типа не велика, и использовать тяжелую артиллерию для подобных случаев просто глупо:
    typedef long LONG;LONG x;

    Сразу был написан класс следующего вида (приводится в сокращенном виде):
    class CPointerDuplacateGuard
    {
      static const size_t QuickMaxSize = 10;
      const void *m_ptrs[QuickMaxSize];
      size_t m_index;
      std::set<const void*> *m_pGuardPointers;
    public:
      CPointerDuplacateGuard();
      CPointerDuplacateGuard(const CPointerDuplacateGuard *parent);
      ...
    };

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

    И вот здесь то я и решил, что пришло время посмотреть на Intel VTune Amplifier XE 2011 beta. Очень хороший повод. Здесь профилировщик как нельзя кстати. Он поможет ответить на вопрос, связано падение производительности только с использованием std::set или замедление вносит само использование постоянных проверок указателя. Если основное падение производительности связано с std::set, то нужно увеличивать значение QuickMaxSize. Это отложит использование std::set на самый крайний случай. Если замедляет сам алгоритм, то думать дальше.

    Сразу скажу, что как следует поработать с Intel VTune Amplifier XE 2011 beta у меня не хватило терпения. Он вводит невообразимое торможение в работу. Хотя у меня достаточно мощная система (4 ядра, 8 Гбайт памяти), если открыто окно Intel VTune Amplifier XE 2011 beta, то даже простое перемещение по коду делается с натугой и рывками. Причем сам Intel VTune Amplifier XE 2011 ничего не делает. Вернее процессор он нагружает, но не пишет, чем занимается. Чтобы не быть голословным приведу демонстрационные скриншоты.

    Для большей наглядности, я прикрепил devenv.exe к 4-тому ядру.
    Picture 3
    Итак, сейчас у меня открыт проект, ничего не происходит. На рисунке видно, что загрузка четвертого ядра близка к нулю:
    Picture 4
    Теперь я просто запускаю Intel VTune Amplifier XE 2011. Подчерку, что только запускаю! Я не выполняю анализ проекта и вообще ничего не делаю. Но четвертое ядро уже занято полностью:
    Picture 6
    Работать становится сразу как-то некомфортно. Среда начинает тормозить везде, где только можно. Если закрыть окно Intel VTune Amplifier XE 2011 то торможение тут же пропадает и загрузка ядра снова становится близка к нулю. Возможно, запущенный Intel VTune Amplifier XE 2011 делает какую-то полезную работу. Но какую непонятно. Если делает — то надо как минимум показать это. У меня сложилось ощущение о какой-то ошибке.

    Торможение меня не остановило, и я приступил к исследованию нашей программы. Для начала я выбрал режим анализа, не собирающий информаций о стеке вызова, но позволяющий понять какие функции тратят наибольшее время:
    Picture 8
    Анализ выполнился без неожиданностей:
    Picture 9
    И я получил полезный результат:
    Picture 10
    Большинство времени тратится в std::_Tree, в функциях выделения и освобождения памяти. Программисту сразу станет понятно, что основное замедление связано именно с использованием std::set.

    Если запустить Amplifier в режиме Hotspot, то проблемное место станет гораздо очевиднее:
    Picture 12
    После этого запуска стало возможным просмотреть стек вызовов. Правда, первый мой запуск в этом режиме закончился неудачей. Меня предупреждали, что с включенной галочкой «Collect accurate CPU time» все будет медленнее. Но получилось как-то слишком медленно. Когда я нажал на кнопку раскрытия стека для первой функции, то так и не дождался результата (ждал 15 минут).

    Запуск уже без галочки показал нужную мне информацию. Но и здесь не могу не добавить ложку дегтя. Функционально инструмент замечателен, но интерфейс безобразен. Все время что-то разъезжается, не перерисовывается, что-то смазывается. Пользоваться неудобно и неприятно:
    Picture 13
    Впрочем, подводил не только внешний вид. Иногда почему-то перебрасывает на не тот участок кода, который необходимо.

    Однако нужный результат я все-таки достиг. Оказалось, что если установить значение массива в 64, то производительность возвращается приблизительно на прежний уровень. Новая подсистема практически не вносит замедления в работу. Исправление:

    static const size_t QuickMaxSize = 64;

    Это подтверждается и Amplifier. Теперь на первый план вышли совсем другие функции, такие как strncmp:
    Picture 15

    Выводы


    Нет счастья в мире программ. Кругом ошибки и недочеты. У и нас в PVS-Studio, и везде. Это не значит, что с ними не надо бороться, но большой шаг хотя бы признать большую сложность программ и что ошибки есть.

    Пост получился несколько критичный по отношению к инструменту Intel VTune Amplifier. Видимо это у меня как у разработчика наболело. Предлагают попробовать очередную программу, которая улучшит мир, а как начинаешь с ней работать, то понимаешь, что больше потратили на маркетинг или красивые картинки, чем на контроль качества. Ну что это за профайлер, который сам тормозит? Сапожник без сапог. :)

    Надеюсь в Release это, или, по крайней мере, многое, будет поправлено. Сам инструмент весьма мощен. Но, к сожалению, пока рекомендовать его использовать не могу. Конечно, подобное писать в блоге Intel как-то не хорошо, зато честно. Надеюсь, разработчики это оценят.
    Intel
    166,00
    Компания
    Поделиться публикацией

    Комментарии 11

      0
      Прочитал с интересом, спасибо. Было бы еще интересней почитать что-то о Code Analyst от AMD, например. В качестве так сказать некоего сравнения.
        +2
        А ну да, пишу в блоге Intel о AMD. Ну что ж, сам виноват )
          +2
          Мы передадим, при случае ;)
          0
          Я как-то смотрел Code Analyst от AMD. Но там писать нечего. :) Он просто не смог правильно интегрироваться в Visual Studio на моей машине. И раз уж у меня критический сегодня настрой: не интегрировался — значит инструмент вообще не работает. Точка. ;)
          +2
          Андрей, спасибо за отличный обзор! Ждите, к вам уже выехали наши специалисты ;)
            +1
            и захватили с собой свежую бету, которая просто летает :)
              +1
              Кстати да, сегодня показывал бету кастомеру — подтверждаю, летает! Правда, один раз долеталась.
                +1
                А мне вот интересно, если Андрей участник Beta программы, а тут выходит летающий Beta Update, наверное должно прийти специальное письмо с предложнением обновить версию?
                  0
                  Что-то я такого ничего не видел в почте…
                    0
                    А вы зайдите на https://registrationcenter.intel.com там все есть :)
              0
              Заранее извиняюсь что спрашиваю не совсем по теме поста, но никак не могу разобраться в некоторых функциях Vtune, может вы подскажите. Например в блоке General Explorations, показатель Assists, я так понял это метрика, показывающая количество передач на преобразование в микрокод, но в чем она измеряется (нет знака %, может это отношение количества всех переданных инструкций, к преобразованным?)? В том же блоке Retiring , если вкратце — то это занятость регистров микропроцессора, но опять же, в чем измеряется этот показатель.
              Искал в мане самой программы, там нет описания в чем измерение, искал на различных форумах, так же, может плохо искал.

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