Хабраиндекс
961,39
7 ноября 2012 в 09:30

Существует ли простая оценка качества оптимизации приложения?

image

Тише едешь дальше будешь...? Оценка производительности.



Больше 7 лет я занимаюсь анализом производительности в составе группы Performance Analysis новосибирского отделения Интел. Мы работаем над улучшением производительности различных приложений, а точнее, ищем способы, с помощью которых ее смог бы улучшить наш компилятор. За это время накопился полезный опыт, который, на мой взгляд, был бы интересен посетителям уважаемого Хабра. Речь в данном случае будет идти не об алгоритмической оптимизации приложений, а о различных модификациях приложений без принципиального изменения их алгоритмов. Понятно, что алгоритмические оптимизации программы тоже имеют право на жизнь, но это совсем другая задача.



Я являюсь разработчиком компилятора Интел, поэтому все мои исследования связаны с различными компиляторными оптимизациями, сравнением различных компиляторов (на Windows это, как правило, сравнение интеловского компилятора с компилятором Microsoft Visual Studio). Собственно поэтому прошу не рассматривать мои посты как рекламу или антирекламу. Для иллюстрации моих мыслей я буду использовать различные инструменты, в том числе и разработанные в нашей компании. Надеюсь, что этот пост вырастет в серию статей об оптимизации приложений.

Существует ли простой критерий оценки оптимальности приложения?



Понятно, что любая проблема и задача, в том числе задача по улучшению производительности приложения, начинается с исследования текущего состояния дел. Необходима оценка: насколько приложение уже оптимизировано, и имеет ли смысл прилагать усилия чтобы его ускорить. На первый взгляд, задача имеет простое решение. Достаточно измерить загрузку процессора, чтобы такую оценку получить. Различные анализаторы производительности позволяют не только замерить время исполнения различных участков программы, но и подсчитать и привязать к коду программы все внутрипроцессорные события, возникающие при ее выполнении. С помощью этой информации можно оценить загрузку вычислительного ядра. Например, определить сколько тактов процессора в среднем потребовалось на выполнение одной инструкции, и какие причины вызывали задержки исполнения Т.е. предлагаемый критерий связывает эффективность работы ядра с возможностью улучшения производительности приложения. А именно, если ядро работает эффективно, то повода для беспокойства нет — программа работает оптимально, в противном случае приложение может быть улучшено и есть смысл заниматься его анализом. В результате использования такого критерия на свет появляются работы, в которых анализируются какие-то процессорные события, и авторы на основе этого анализа строят предположения о возможностях улучшения производительности приложений. Возможно, такие методы работы действительно полезны для архитекторов вычислительных систем и дают им возможность пофантазировать об улучшении архитектуры процессора. Но, к сожалению, для программиста, размышляющего об улучшении производительности своего приложения, этот метод крайне сомнительный, редко работает и не дает ответа на извечный вопрос русской интеллигенции: «Что делать? и Можно ли есть курицу руками?».
Во многих случаях максимальная загрузка вычислительного ядра вовсе не значит, что невозможно улучшить производительность программы и наоборот.
Давайте рассмотрим простой тестик с перемножением прямоугольных матриц. Создание маленьких работающих примеров, на мой взгляд, лучший метод получения интересной информации об устройстве вселенной и, в том числе, о работе компиляторов и процессоров. В таких тестах важно, чтобы время исполнения исследуемого кода было достаточно велико, чтобы на него не влияло время загрузки программы и какие-то случайные события, поэтому можно исполнять исследуемый код много раз.

#include <stdio.h>
#include <stdlib.h>
#define N 200
#define T 100

void matrix_mul_matrix(int t, int n, double *C, float *A, float *B) {
int i,j,k;
  for (i=0; i<t; i++) 
    for (j=0; j<t; j++) 
      for(k=0;k<n;k++)
                C[i*t+j]+=(double)A[i*n+k] * (double)B[k*t+j];
}

int main() {
float *A,*B;
double *C;
int i,j;

//... Выделение памяти и инициализация массивов 

for(i=0;i<10000;i++) 
  matrix_mul_matrix(T,N,C,A,B);

printf("%f %f %f\n",C[0],C[1],C[100]);
free(A);
free(B);
free(C);
}



На моей лабораторной машине c Windows Server 2008 R2 Enterprise и процессором Intel Xeon X5570 я компилирую эту программу с помощью компилятора Майкрософт VS 10.0. и Интел Parallel Studio XE2013. Для простоты я работаю с командной строкой и беру опции, соответствующие релизовскому варианту компиляции, используемыми по умолчанию в Visual Studio.

cl matrix.c /O2 /GL /GS /GR /W3 /nologo /Wp64 /Zi -Ob0 -Fematrix_cl
icl matrix.c /O2 /GL /GS /GR /W3 /nologo /Wp64 /Zi -Ob0 -Fematrix

Выясняется, что время работы matrix_cl равно ~21.9 s, в то время как время работы matrix равно ~9.3 s.

Теперь посмотрим, что нам скажет Amplifier о загрузке процессора. Intel VTune Amplifier XE 2011 – это как раз инструмент для оценки производительности, позволяющий работать с процессорными событиями интеловских процессоров.
Давайте создадим в Amplifier два проекта для полученных приложений и сделаем предварительный анализ – general exploration. Ну и что мы в результате видим? Вот результаты «разведки» приложения matrix_cl:

image

Обращаем внимание на CPI Rate (Clock per instruction, среднее количество тактов на одну инструкцию). Для моего процессора теоретический минимум этой величины 0.25. (Параллельное исполнение 4-х инструкций на 4-х исполнительных устройствах). Число CPI 0.546 считается очень хорошим. Есть конечно и задержки. Но, вроде ничего критического нет. Вычислительное ядро работает с хорошей нагрузкой, и все выглядит вполне прилично. Можно ли из этой оценки понять, что производительность приложения реально улучшить более чем в два раза?
Результаты исследования для matrix:



Волшебное улучшение производительности более чем в два раза, практически никак не отразились на основных «рейтингах» вычислений, собираемых Intel VTune Amplifier XE 2011. Т.е. исследование работы процессора в данном случае не дало нам никаких сигналов о том, что производительность может быть кардинально улучшена.

Данное улучшение производительности было достигнуто благодаря автовекторизации. Это легко увидеть, если добавить к опциям для интеловского компилятора –Qvec_report. Компилятор выдаст

...\matrix.c(9): (col. 5) remark: PERMUTED LOOP WAS VECTORIZED.

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

Теперь возьмем пример другого рода и создадим программу, которая будет обходить длинную цепочку объектов:

#include <stdio.h>
#include <stdlib.h>
#define N 1000000

struct _planet {
  float x;
  float y;
  float z;
  double m;
  struct _planet *prev;
  struct _planet *next;
} ;
typedef struct _planet planet;

planet*  init_chain() {
   Создание и инициализация цепочки
}

int main() {
planet *planet_chain;
planet *cur;
int i;
double sum=0.0;

planet_chain=init_chain();

for(i=0;i<1000;i++) {
   cur=planet_chain;
   while(cur) {
     sum += cur->m;
     cur=cur->next;
   }
}
printf("%f\n",sum);
}


Оба оптимизирующие компилятора создали приложения выполняющиеся ~6.2s. Amplifier сообщает о том, что в данном приложении все плохо:

image

CPI rate очень плохой, и большую часть времени вычислительное ядро ожидает получения данных для обработки.
Ну и что с этим делать? Допустим, мы продолжим исследования и установим, что причиной плохой загрузки вычислительного ядра является задержка с работой подсистемы памяти. Очевидно, что ядро загружено плохо. Но нам то это сакральное знание чем помогает? Какие существуют методы для улучшения работы подсистемы памяти? Позволяет ли специфика нашего приложения применить уже известные методы?
Это пример приложения, в котором все плохо, и ситуацию нельзя кардинально исправить без изменения алгоритма.

заключение



Таким образом, простые вычисления различных процессорных коэффициентов дают мало информации для оценки эффективности приложения.

В данном случае простым аналогом задачи по оценке эффективности выполняющегося приложения является спортсмен, двигающийся из точки A в точку B. Если мы возьмем за критерий оптимальной работы спортсмена нагрузку на его мышцы или сравним среднюю его скорость на трассе и максимальную скорость, с которой данный спортсмен может двигаться, то далеко ли мы уйдем с такими критериями? Если спорсмен дурной, хоть и очень сильный, и постоянно ломится через чащу, вместо того чтобы оббежать ее по тропинке, то нужен просто более умный спортсмен. Обратно, если спортсмен бежал медленно, но его путь пролегал по болоту, где приходилось останавливаться, нащупывать путь и даже возвращаться периодически назад, то виноват ли спортсмен? Можно привлечь к решению задачи более тренированного и быстрого атлета (за большие деньги), а можно – грамотного тренера, который на старте проанализирует трассу забега, сильные и слабые стороны бегуна, а затем предложит бегуну оптимальный маршрут, а возможно, научит его принимать на ходу правильное решение в каких-то простых ситуациях.
Одним словом, без анализа пути, который нужно было преодолеть и знаний сильных и слабых сторон атлета, трудно оценить насколько он реально был хорош на дистанции.

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

1.) Основные проблемы, влияющие на производительность процессора, и методы оптимизации, влияющие на эти проблемы.
2.) Основные методы компиляторной оптимизации. Как правило, все те методы, которые могут помочь улучшить производительность программы уже как-то учтены и реализованы в существующих оптимизирующих компиляторах. Полезно знать инструмент, которым вы пользуетесь в своей работе. Возможно, к успеху ведет простое добавление еще одной опции. Интересно выяснить, умеет ли ваш компилятор делать ту или иную оптимизацию, и почему он не сделал ее для вашего кода?
3.) Многие из известных оптимизаций эффективно могут быть сделаны руками. В каких случаях можно попробовать их сделать? Когда применение той или иной оптимизации выгодно и почему?

Соответственно, в дальнейшем я попробую представить образец такой методологии и расскажу об известных мне полезных методах оптимизации приложений.
+21
7777
57
andrei_an 10,5
Похожие публикации
Профилировка производительности OpenMP приложений 2 декабря 2013 в 09:24
Межпроцедурный анализ и оптимизации (I) 29 октября 2013 в 09:52
«Зачем обновлять GCC компилятор?» или «Производительность GCC компилятора на Intel Atom от версии к версии» 1 августа 2013 в 09:00
Запуск Intel Haswell в России. Битва за производительность продолжается 7 июня 2013 в 14:27
Будущее роста производительности: долгосрочные перспективы 6 мая 2013 в 08:53
Презумпция виновности программиста или почему компилятор иногда «тупит» 24 декабря 2012 в 14:55
Разбиение цикла как пример высокоуровневой оптимизации 3 декабря 2012 в 15:15
Основные проблемы влияющие на производительность вычислительного ядра и приложения и методы их решения компилятором 15 ноября 2012 в 14:36
Разница в подходах анализа кода компилятором и выделенным инструментом 1 ноября 2010 в 21:23
Регулярное использование статического анализа кода в командной разработке 8 сентября 2010 в 11:45

Комментарии (42)

+3
eastig, #
Я бы не сказал, что из сравнения предварительных анализов Amplifier нельзя объяснить прирост.
Видно, что для matrix_cl

INST_RETIRED 1.20926e+11

а для matrix

INST_RETIRED 5.687e+10

То есть для той же работы потребовалось в два раза меньше инструкций. Если считать, что в среднем время исполнения одной инструкции в обеих версиях программы одинаково, то и получаем двукратное ускорение. Уменьшение количества инструкций сразу наталкивает на использование SSE, а значит и на векторизацию.

Так же из сравнения отчетов видно что есть проблемы с Front-End — это сильное отличие Instruction Starvation, а также сильно отличаются retire stalls.

Хорошо было бы показать распределение клоктиков по коду программы.
0
andrei_an, #
Прирост производительности конечно можно объяснить, но нельзя сказать, без анализа алгоритмов приложения, можно или нет получить какой-то выигрыш от векторизации. Нельзя сказать — нет SSE инструкций, значит возможен выигрыш от векторизации. В какой-то совсем оторванной от жизни теории — это так. Но в реальности нужно исследовать есть ли правильные циклы, есть ли в них цикловые зависимости. Ну и обрабатываемые данные должны правильно лежать в памяти, чтобы от векторизации был толк. Разве не так?
+1
eastig, #
Конечно, же так.

Вы пишите, что улучшение было достигнуто благодаря векторизации. Но цепочку рассуждений откуда это следует вы не привели. Я же хотел показать, что из ваших данных это можно было вывести следующим образом:

1. Сократилось количество инструкций.
2. Смотрим ассемблер горячих путей программы.
3. Если находим SSE, то цикл+SSE наводи на мысль о векторизации.
4. Проверяем с помощью отчета компилятора о векторизации.

А если скомпилировать VS 2012, то что получится? Майкрософтовский компилятор тоже поддерживает авто-векторизацию.
+1
andrei_an, #
Вы слегка поменяли мою мысль. Я спрашиваю, можно ли сделать заключение о том, может или нет производительность быть улучшена, измерив какие-то процессорные события. И привожу в качестве примера оптимизацию автовекторизация — которая действительно значительно улучшает производительность, но заключения о том может ли она быть сделана или нет нельзя получить без исследования кода программы.
Вы же мне показываете, что из сравнения двух рапортов Amplifierа можно понять за счет чего получен положительный эффект. С этим вашим рассуждением я абсолютно согласен. В данном случае можно. Мне было проще. Я когда подбирал тест уже знал чего хочу достичь и сразу использовал опцию -Qvec_report, чтобы увидеть автовекторизацию.
Что же касается сравнений автовекторизации разных компиляторов, то эта хорошая тема для отдельного исследования.
+2
eastig, #
Что касается второй программы.
Вряд ли здесь компилятор что либо может сделать без помощи программиста.

Мы имеем проход по списку. Современные суперскалерные архитектуры очень не любят списки, так как очень сложно что-либо предсказать. Префечеры не срабатывают, начинаются задержки связанные с загрузкой данных из памяти. Фактически out of order режим перестает работать.

+1
andrei_an, #
Компилятор умеет кое-что делать для таких случаев, в основном пытаясь повысить компактность используемых данных. Есть оптимизации перестановки полей, вынесения холодных полей в отдельные структуры и т.д. Только для этого нужно массу требований выполнить. Т.е. простые оценки опять не помогают — нужно исследовать каждый конкретный случай.
+1
mejedi, #
Есть оптимизации перестановки полей, вынесения холодных полей в отдельные структуры и т.д.

Для какого языка возможны эти оптимизации? В случае Си декларация однозначно определяет представление структуры в памяти. Максимум — можно добавить паддинг и выравнивание, но скажем поменять порядок следования полей уже нельзя.
+1
andrei_an, #
Если вы не планируете отлаживать свое приложение, ставите максимальный уровень оптимизации, то для компилятора нет никаких ограничений в используемых трансформациях вашего кода, кроме выдачи в итоге верного результата. Понятно, если вы обращаетесь к элементам вашей структуры каким-нибудь хитрым способом через офсеты и указатели, то компилятор должен заметить ваш высокий проффесионализм и понять что ему лучше здесь отдыхать и не вмешиваться.
0
mejedi, #
… то для компилятора нет никаких ограничений в используемых трансформациях вашего кода, кроме выдачи в итоге верного результата

Неверно. Есть стандарт языка. Если в результате применения трансформации возникает нарушение стандарта, такая трансформация нелегальна. Как именно должна быть представленна структура в памяти прописано в стандарте, делать по другому вы просто не имеете права.

То, что структура представлена в памяти определенным образом, важно для бинарной совместимости разных единиц трансляции, библиотек и интерфейсов ОС.

Традиционно, работа с бинарными форматами в Си происходит через структуру — инициализируем значения полей (возможно с преобразованием big/little endian), и пишем весь блок памяти целиком в файл или отправили по сети.

Ну и обращаться к полям структуры «хитрым способом через офсеты и указатели» вполне легально в рамках языка Си.
+3
andrei_an, #
Вы так оставите без работы массу людей, которые пишут умные книги типа «Optimization compilers for modern architectures». Они, наивные, используют в своей жизни детский принцип «Если мама не увидит, это маму не обидит» :)
На самом деле никакого противоречия с бинарной совместимостью не возникает, поскольку все такие оптимизации делаются при создании исполняемого файла при наличии полного набора исходников. В объектных файлах и библиотеках вы ничего подобного не увидите.
Согласен. В рамках языка Cи много легальных вещей, которые осложняют жизнь компиляторам да и самим разработчикам. Иногда даже вводяться правила типа ansi_alias rules, чтобы ограничить креативность разработчиков. Задача компилятора сделать консервативный анализ, то есть доказать, что та или иная оптимизация корректна и не изменяет результаты работы приложения.
0
mejedi, #
Справедливости ради, спецификация языка Си написана так, чтобы максимально «развязать руки» компиляторщикам. Например, порядок вычисления аргументов в функциях может быть любым, и так далее.

Задача оптимизации представления структур данных в Си, так чтобы никто не «поймал за руку», адски сложная и мало перспективная в плане возможного выигрыша в производительности задача. ИМХО.

Спрошу прямо: компилятор интела умеет делать такую оптимизацию для Си? Или другого языка?
+1
andrei_an, #
Ну я думаю вы сильно ошибаетесь в оценках полезности таких оптимизаций для производительности. Я надеюсь приведу в будущем пару примеров, которые вас удивят.
Не вижу никакой сложности в изменении порядка полей в структуре.
Компилятор умеет делать такие оптимизации, но здесь сложно бывает доказать именно корректность. Руками программист может все делать гораздо эффективнее, но для этого нужно понимать, на что такие модификации влияют.
0
mejedi, #
Не вижу никакой сложности в изменении порядка полей в структуре. Компилятор умеет делать такие оптимизации, но здесь сложно бывает доказать именно корректность.

А я вижу. Можно подробности? Какой компилятор, активна ли эта оптимизация по умолчанию или как ее включить?

Ну я думаю вы сильно ошибаетесь в оценках полезности таких оптимизаций для производительности.

Оптимизация важная, спора нет. Только это задача программиста, ИМХО.

Руками программист может все делать гораздо эффективнее....

Вот именно. У программиста банально больше возможностей в проектировании своих структур данных.
+1
andrei_an, #
Есть в интеловском компиляторе такой набор опций — Qprof_use и -Qprof_gen. С этими опциями компилятор сначала делает инструментированный код, затем собирается статистика про выполнение приложения (тестовые прогоны) и на основе сбора этой статистики приложение еще раз пересобирается с ее учетом. Понятно, что приложение должно гоняться на представительном наборе данных. Тогда появляется возможность оценить вес использования тех или иных полей. Компановка вместе наиболее часто используемых полей должна снижать нагрузку на шину данных. Плюс к этому, наверняка, должна быть включена межпроцедурная оптимизация, чтобы проверить, что поля можно двигать. Как-то так, если коротко.
А если длинно, то нужно сделать отдельный пост по этой теме.
Про другие компиляторы не скажу — не изучал вопрос.
Удовлетворяет такой ответ?
0
mejedi, #
Конкретики от вас видимо не дождешься)

Я поискал статьи на тему автоматической оптимизации структур данных; нашлось несколько штук [1,2,3]. У всех масса ограничений, которые ставят под сомнение применимость твкой техники в автоматическом режиме в языке Си.

Но будем считать, что Intel удалось совершить чудо.
0
andrei_an, #
Ну если выше не конкретика, то я пас.
Про ограничения я написал.
И Да! Мы здесь в Intel делаем чудеса :)
Хотя чудес я тут не вижу. Нужно посмотреть какие-то конкретные примеры и оценить область применимости данных оптимизаций. Она, скорее всего достаточно узкая.
0
mejedi, #
Разумеется, это не конкретика.

Смотрите — есть оптимизация, про которую на сайте интел написано «structure spliting and field reordering», а еще сказано, что нужно для этого активировать IPO. И все.

Насколько можно рассчитывать на эту оптимизацию, когда это работает, а когда нет — не ясно. Видимо надо воспринимать эту оптимизацию как приятный дополнительный бонус (может быть, а может не быть) и особо на нее не рассчитывать. То есть продолжаем аккуратно проектировать структуры данных вручную, так?

Далее. Компилятор может давать советы о переупорядочивании полей. Это меня как раз не удивляет. А вот то, что можно в автоматическом режиме убедиться, что код не сломается, если переставить поля — вот это похоже на магию. В контексте языка Си, разумеется.
+1
andrei_an, #
Так «неконкретное» поведение компилятора характерно практически для каждой оптимизации. Сначала нужно доказать, что оптимизацию можно делать. Доказательство может быть сложным и требовать много ресурсов, поэтому в любой момент компилятор может отказаться от дальнейшего исследования и отказаться от оптимизации. Далее нужно как-то оценить выгоду от оптимизации. И здесь может быть много факторов. Если взять для примера автовекторизатор, то он может сообщить о зависимостях, о плохой структуре цикла, о том что векторизовать невыгодно и т.д. В результате спрогнозировать, какие оптимизации будут применены в том или ином случае достаточно сложно.
Компиляторные оптимизации действительно работают часто как дополнительный бонус и многих это устраивает.
В чем магия-то? В том что нужно проверить все исходные файлы и убедиться что поля структуры всегда адресуются через их имена и никогда через указатели с какими-нибудь офсетами?
0
mejedi, #
Так «неконкретное» поведение компилятора характерно практически для каждой оптимизации.

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

нужно проверить все исходные файлы и убедиться что поля структуры всегда адресуются через их имена и никогда через указатели

Не только. Еще нужно убедиться, что структура в бинарном виде никогда не покидает пределы системы (сохранение в файлы и тп). Еще к полям может осуществляться доступ через структуру другого типа (распространенный Си трюк для эмуляции наследования).
0
izard, #
Увидел ссылку на перестановку полей в памяти, и сразу же подумал на PGO. PGO — единственная оптимизация, которая может переставлять поля в памяти?
+1
andrei_an, #
Думаю PGO и использование динамического профилировщика здесь действительно необходимо, потому что оценить частоту использования полей с помощью статического профилировщика проблематично, хотя в каких-то вырожденных случаях (поля вообще не используются) такое в принципе возможно.
Спасибо за вопрос.
+1
LeiTZ, #
Часто стиль написания кода сам по себе сильно мешает компилятору оптимизировать.
На днях наткнулся на интересную особенность в GCC (возможно справедливо и для остальных компиляторов, я не проверял) — при векторизации циклов результат зависит от мест слагаемых из-за редукции:
Векторизуется
for(i=0;i<n;i++) s += a[i] + b[i];
и
for(i=0;i<n;i++) s = a[i] + b[i] + s;
Не векторизуется
for(i=0;i<n;i++) s = s + a[i] + b[i];
0
hack2root, #
А параметры компиляции можно в студию? Как то не верится что всё вот так просто.

s = s + (хвост)

и

s = (голова) + s

должны нормально векторизоваться… попробуй так

s = (a[i] + b[i]) + s

и

s = s + (a[i] + b[i])

Так как по умолчанию, скобки расставляются так:

s = s + (a[i] + (b[i]))

То есть разница в построенном дереве AST, как мне кажется, и оптимизации

s = s + (хвост) в s += (хвост)
0
LeiTZ, #
В параметрах ничего особенного не было. Разница тут действительно в построенном дереве и в том, что получает векторизатор в виде SSA — в случае с векторизуемым циклом получается s_23 = _22 + s_33 и подобное, а в другом случае:
_21 = _20 + s_33;
_22 = MEM;
s_23 = _21 + _22;
и два сложения с s ставят компилятор в тупик.
Хотя по логике обработки сложений всё правильно.
–6
hack2root, #
Ответ очевиден. С точки зрения скорости работы. В некоторых процессорах перемножение матриц может быть осуществлено за один такт. В некоторых нет. Давайте сравним возможности.

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

Неэтично сравнивать Бугатти Вайерон и пирожок. Мне лично не хочется комфортно врезаться на полной скорости в какую-нибудь отсталую архитектуру, вроде 386. Поэтому, предлагаю, взять в зубы MASM, включить хедеры для последних нововведений в процессорах SSE3/SSE4, и сравнить с оптимизацией руками и головой, на конкретных алгоритмах типа FFT, нейронные сети, поиск на графах. Если человеку не удастся заставить выполняться программу быстрее, значит выиграет компилятор.

А так — странно даже. VC10 будет всегда работать хуже, так как известно, что Intel скрывается важная информация о внутреннем устройстве процессора, что называется «для внутреннего пользования», поэтому все ваши посты превратятся в рекламу вашего нового продукта Parallel Studio 2013.

Будет лучше, если вы будете сравнивать ваш продукт с самим собой. Например, чем продукт 2013 года лучше установленного продукта 2012, прогоните на тех же самых примерах из поста и, думаю, вы не увидите никакой разницы.

По моему будет лучше сравнивать gcc c++ с максимальными настройками для векторизации и оптимизации, а не мучить старушку VC 10. Она вам лично ничего плохого не сделала.

Сравнивайте компиляторы Intel только с компиляторами Intel.

+1
eastig, #
Откуда такая уверенность, что Майкрософт не имеет доступ к информации? Проблема скорее всего в том, что нет достаточного количества специалистов, чтобы все это реализовать в компиляторе.
+4
andrei_an, #
Нужно обращаться сразу с претензиями к Spec.org. Они делают перечисленные вами неэтичные вещи и постоянно сравнивают коды полученные с помощью разных компиляторов на разных вычислительных архитектурах. Да еще деньги за это получают.
Понятно, что разные компиляторы делают разные наборы оптимизаций с одним и тем-же набором опций, но в данном случае сравнение компиляторов — вовсе не тема данной статьи.
Собственно, я мог бы сравнит «старушку» VS2010 c каким-нибудь «древним» интеловским компилятором. Но результата это бы не изменило, поскольку автовекторизатор в интеловских компиляторах появился давно, а в VS только в VS2012.
Открою вам тайну, есть много людей, которые полагают, что Microsoft скрывает важную информацию об устройстве своих операционных систем.
Почему вы ограничиваете меня в инструментах по познанию мира :)?
+2
spiff, #
Нужно ребятам из VTune/Aplifier намекнуть, что наличие высокоуровневых отчетов «для блондинок» вроде «Ваше приложение оптимизировано. Можно расслабиться.» или «Чувак, ты это пьяный писал?» — очень полезная вещь. Не всем нужно понимать все эти юниты, клок-тики, метрики, события, семплы и т.д. Кроме того, из поста я понял, что можно практически определить степень оптимизации кода, на основе метрики: тики на инструкции. Ведь так?
0
andrei_an, #
Не совсем — скорее наоборот.
Если спортсмен бежит с полным напряжением сил по длинной дороге, то он в итоге может уступить и черепахе, идущей коротким путем.
0
spiff, #
Кстати да. Не подумал о том, что может быть изначально выбран не тот алгоритм. Но с другой стороны, это уже точно не проблема тула, анализирующего код. Он (тул) просто смотрит на сколько оптимально выполняются инструкции на конкретном железе. Т.е. детали реализации его мало интересуют. Так что, тулу вполне себе можно говорить, о том «на сколько оптимально код работает на железе», а не «на сколько оптимально он решает поставленную задачу».
0
andrei_an, #
Согласен. Тул при анализе полезен и во многих случаях хорошо помогает. Но он очевидно не панацея и делать какие-то далеко идущие оценки без анализа приложения довольно бесперспективно.
0
izard, #
Почему Vtune 2011, а на 2013?
0
andrei_an, #
В будущем исправлюсь.
0
eastig, #
Эксперимент проводили на Xeon X5570, процессор 2009 года выпуска. Так что особого смысла в VTune 2013 нет.

Вот если бы что-то из серии E7.
0
izard, #
Ну в 2013 много полезного кроме поддержки более свежего железа и java. Надеюсь коллеги напишут топик, а то только про инспектор 2013 писали недавно.
0
Fragster, #
В своих системах для оценки используем en.wikipedia.org/wiki/Apdex
0
eastig, #
Это не совсем то, как мне кажется. Этот стандарт больше для менеджмента и репортинга.
0
Fragster, #
Ну, тут просто от результата идет весь процесс, т.е. мы сначала задаем целевые показатели, а потом начинаем оптимизировать. Если у нас нет четких критериев, какова должна быть производительность для пользователя — оптимизация бессмысленна.
0
eastig, #
Насколько я понял из описания, все сводится к одной чиселке, которая зависит от числа удовлетворенных пользователей. Получили тестовую версию продукта. От группы тестеровщиков получили отзывы. Посчитали чиселку. Вышло ниже заданного показателя. Значит нужно улучшать качество продукта. Эта оценка говорит нужно ли проводить оптимизацию или нет, но она не может сказать возможно ли провести оптимизацию. Так же эта оценка позволяет оценить качество проделанной работы.

В статье же ставится вопрос: Если необходимо улучшить производительность приложения, то на основании каких оценок можно понять, что это возможно. Было показано, что эффективная загрузка процессора является необходимым, но не достаточным критерием. При хорошей эффективной загрузке, можно было ускорить программу не переписывая ее.
0
Fragster, #
Статья не дает ответ на вопрос: а что если выбран в принципе не тот алгоритм? если инструмент/библиотека не оптимальны для таких случаев? И т.п. Она дает ответ на вопрос только «насколько существующий алгоритм использует возможности моего процессора». Зачастую маленькое изменение бизнес-логики (или пересмотр используемых индексов, или нахождение другой реализации задачи, или даже выполнение проверок в другом порядке) дает намного более существенный прирост, чем тонкая оптимизация из-за неоптимального доступа к памяти, который не дает использовать какие-нибудь инструкции от SSE. Я, конечно, говорю об учетных и бизнес системах. В играх и научных расчетах ситуация может отличаться существенно (хотя уже почти везде начинают решать задачи «в лоб», полагаясь на огромную производительность современных компьютеров).
0
vikky13, #
В идеале деле у инструмента оценки производительности должно быть две опции: оценка производительности реализации существующего алгоритма на данном CPU и оценка оптимальности самого алгоритма. Последнее можно делать просто по базе алгоритмов — типа «вот вы тут простые числа ищете, а для этого есть алгоритмы в пять раз лучше». Шучу, конечно, но хотелось бы такого.
+1
spiff, #
Ну какие уж тут шутки. Интелосвский компилятор уже двигается в этом направлении и умеет распознавать некоторые алгоритмы. Например — умножение матриц, которое он, при соответствующей опции может заменить на вызов в MKL. Получается пишешь глупый код, который работает медленно, а компилятор просто заменяет его на один вызов и все летает.

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