Здравствуйте, alex_public, Вы писали: _>Так, поясню ещё раз, более просто: у меня нет никакого желания улучшать работу MSVC, а вот желание пообщаться с коллегами по форуму у меня есть. )
Offtop
Ну я тоже поясню в последний раз. Я не посягаю на Ваши желания. Но Ваш экзальтированный тон текста напомнил мне — "я бежала за Вами 2 часа, чтобы сказать, что Вы мне безразличны" (с). Случай же с багом совершенно рутинный, а тут было столько экспрессии ("шедевр", "ТАКОЕ" и т.п.). Я попытался рассказать Вам, как сделать это более профессионально. Примеры на форуме есть. В общем-то ничего личного и надеюсь не обидел/задел.
забавное сообщение, на которое я собирался ответить прямо там в темке, отметив что не стоит браться за тесты производительности тем, кто не может выставить правильные опции компиляторам, а пользуется только дефолтными (а они очень разные у разных компиляторов). Однако перед написанием ответа я решил всё же установить компилятор от MS, чтобы удостовериться, что за прошедшее время ничего не изменилось и он по прежнему слабенький, как я и говорил. Но в процессе этого теста вылезло ТАКОЕ, что я сразу же забыл об изначальной дискуссии и решил написать отдельное сообщение про это.
И так, я взял тесты предложенные моим собеседником в изначальной теме. Они конечно довольно сомнительные, но почему бы не проверить и на них (ведь хороший продукт должен качественно оптимизировать любой код). Только я их слегка переписал, чтобы ими можно было адекватно пользоваться (GUI в тестах???) и чтобы не было совсем стыдно за код. Но ключевая часть осталась неизменной (как я наивно думал):
код теста
#define _USE_MATH_DEFINES
#include <cmath>
#include <chrono>
#include <iostream>
using namespace std;
constexpr auto N_MULTIPLY=10000000;
constexpr int N_GENERATED=1000;
int randoms[N_GENERATED];
int outputs[N_GENERATED];
double randoms_dbl[N_GENERATED];
double outputs_dbl[N_GENERATED];
template<typename F> void Measure(F f)
{
auto start=chrono::high_resolution_clock::now();
for(int i=2; i<N_MULTIPLY; i++){
for(int j=0; j<N_GENERATED; j++) f(i, j);
//if(i==0) cout<<"msvc????????????????????";
}
auto end=chrono::high_resolution_clock::now();
cout<<chrono::duration_cast<chrono::milliseconds>(end-start).count()<<" ms."<<endl;
}
int main()
{
for(int i=0; i<N_GENERATED; i++){
randoms[i]=rand();
randoms_dbl[i]=1.11*rand();
}
Measure([](int i, int j){
auto result=randoms[j]*i;
result++;
outputs[j] = result;
});
Measure([](int i, int j){
auto mult=i*1.1;
auto result=randoms_dbl[j]*mult;
result+=1.555;
outputs_dbl[j]=result;
});
Measure([](int i, int j){
auto mult=i*2*M_PI;
auto result=randoms_dbl[j]+sin(mult);
result+=0.375;
outputs_dbl[j]=result;
});
}
Так вот запустив этот код (правда тогда в нём не было закомментированной строки) я получил такой замечательный результат:
Не, я конечно и делал этот тест для демонстрации преимущества gcc, но разница более чем в 100 раз показалась всё же каким-то перебором. Тем более, что мой собеседник демонстрировал совсем других цифры. Тут была явно какая-то ошибка. Но я не мог подумать на компилятор и начал искать у себя — перебирал разные опции компилятора, варианты подключения библиотек и т.п. Но ничего не помогало. Я уже даже начал думать о магическом влияние Qt и т.п. невероятных вещах, когда мне в голову пришла совершенно наркоманская мысль: у моего собеседника в теле цикла было уведомление GUI о прогрессе прохождения теста (которое я естественно выкинул при переписывание) — поставлю ка и я нечто подобное (закомментированная строка в коде выше, причём самое забавное, что cout там никогда не выполняется). И что вы думаете? Оно заработало нормально:
Эти результаты меня уже ничем не удивили — всё как я и предполагал, gcc быстрее, но на небольшие проценты.
Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
P.S. Возможно это уже общеизвестная тут информация, а это только я не знал про данную "особенность". Просто я уже давно не пользуюсь продуктом от MS и поэтому был не в курсе, а сейчас столкнулся и решил поделиться.
P.P.S. В тесте использовались компиляторы: MinGW4.9.2/MingGW6.3.0 (между ними нет разницы на данных тестах) и "Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506".
Update 13.03.17. В ходе дискуссии я написал ещё один вариант теста, уже не для измерений производительности, а для демонстрации сути проблемы (т.к. по результатам данного теста возможно не все поняли глобальность проблемы — она явно не в использование синуса) в компиляторе от MS: http://rsdn.org/forum/cpp/6723478.1
Так же судя по сообщениям коллег с форума можно локализовать данную проблему по версиям MSVC: подвержены версии VS 2013, 2015, 2017. И для 32-ух и для 64-ёх битного кода.
Я не поленился и сделал bug report — connect.microsoft.com
Предмет бага — разный уровень оптимизации для очень близкого кода. Посланный код основан на rsdn
P.S.
Хотел бы еще раз отметить, что для этого вырожденного кода включение оптимизации в одном случае дает выигрыш в 27 раз, а в другом в 1.5. При идеальной же оптимизации выигрыш должен был быть в N_MULTIPLY = 1000000 раз. С этим не справился ни один компилятор...
P.P.S.
Самого кода пока не видно. Они декларируют задержку в появлении загруженных файлов от нескольких часов до суток.
Здравствуйте, alex_public, Вы писали:
_>Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
Такое ощущение, что Вы в первый раз в жизни увидели ошибку компилятора...
Как поступают профессионалы:
1) Сокращают код до необходимого минимума и посылают bug репорт производителю. Для компилятора от MS это https://connect.microsoft.com/VisualStudio
2) Если очень хочется поделиться о баге на форуме, то даете ссылку на bug report и (так поступают настоящие профи) делаете ассемблерный листинг и показываете сообществу где именно облажался компилятор. На RSDN это можно регулярно встретить.
P.S.
если Вы полазите по bug трекеру любого компилятора, то увидете множество удивительных примеров кода, в которых компилятор лажается. Очень поучительно, чтобы не давать заголовки, которые Вы дали вашему сообщению, и потерять веру в безгрешность компиляторов.
Здравствуйте, koandrew, Вы писали:
K>Его "стиль" напоминает мне ребёнка, который нашёл лужу и теперь прыгает в ней, пытаясь обрызгать как можно больше окружающих
О, я смотрю тебе очень хочется написать что-нибудь и в профильном разделе форума, а не только в "политике" или "о жизни". Но при этом никакой технической информации по данной серьёзной профильной теме ты из себя выжать не смог, так что решил по привычке сразу перейти к обсуждению участников дискуссии. Только боюсь тебя огорчить, но в данных разделах форума подобное никому не интересно. )
Здравствуйте, alex_public, Вы писали:
_>О, я смотрю тебе очень хочется написать что-нибудь и в профильном разделе форума, а не только в "политике" или "о жизни". Но при этом никакой технической информации по данной серьёзной профильной теме ты из себя выжать не смог, так что решил по привычке сразу перейти к обсуждению участников дискуссии. Только боюсь тебя огорчить, но в данных разделах форума подобное никому не интересно. )
У тебя мания величия, если ты думаешь, что твоё мнение о том, кто и где что может писать кому-то интересно.
В 1-м случае синус вычисляется на каждой итерации вложенного цикла (call sin), во 2-м случае вычисление синуса вынесено на верхний цикл (call __vdecl_sin2).
Что характерно в обоих вариантах используются разные реализации синуса, которые как пишут дают разный результат
После того как я послал bug report в MS, я решил проверить, а как справляется с этим вырожденным примером CLang (по мнению многих лучший компилятор нашего времени). Так как toolset Clang установлен у меня в VS2015, то это делается переключением toolset в настройках проекта.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, LaptevVV, Вы писали:
S>>>На 64 битах результат подтверждаю. LVV>>В смысле — в 100 раз хуже gcc?
_>В 100 раз хуже и gcc и себя самого (но только при наличие никчемной строки).
Не нужно потешаться над такими сложными продуктами как компиляторы. Мне приходилось очень часто сталкиваться с багами как GCC, так и MSVC.
Вот к примеру чуть более года назад столкнулся с ошибочной кодогенерацией GCC 4.8, который предоставляет Google для сборки андройда. Собирал я тогда 6-ой андройд для мобилки (до этого собирал 4-ый андрой при помощи GCC 4.7). Так вот после сборки оказалось, что WiFi драйвер по страшному чудит. В dmesg логе было видно место возникновения паники, но в этом месте ничего криминального не было. При чём небольшое изменения кода смещало место возникновения паники.
При исследовании при помощи изменения кода и просмотра ARM кода в IDA удалось понять, что бага не в коде, а в компиляторе. И проблема была в том, что эта версия GCC при обильном инлайне нескольких функций начинала некорректно работать с переменными на стеке. В IDA отчётливо наблюдал тот факт, что место на стеке использовалось несколькими переменными. Т.е. с какого то перепугу GCC посчитала, что далее по коду переменная Х уже не используется и можно регистр R использовать для новой переменной N. И это была роковая ошибка GCC (регистр R содержал лютую дичь), из-за которой сбой происходил только после нескольких возвратов из функций.
Использование GCC 4.9.4 решило проблему.
А буквально недавно пришлось компилить OpenSSH-Win32 под VS2010 SP1. Так вот при линковке sshd.exe линкер просто падал. Но подал с выдачей названия c-файла, который он посчитал дурным. Довольно быстро локализовал проблемное место: обычный switch и три case. Пришлось один из кейсов вынести за предел switch'а , что бы кодогенерация была корректной. В дизасм заглядывать было влом.
Здравствуйте, Serg27, Вы писали:
S>Конечно для оценки качества генерации компилятора использовать код такого типа нельзя, так как время выполнения может быть от 0 (просто сгенировать нужный массив на этапе компиляции/загрузки) до плохо оптимизированного. Не зря же используют какие-то более реальные задачи со сложным кодом для проверки оптимизации компилятором.
Очень даже можно. ) Так и представил себе увлекательный поиск решения данной проблемы внутри сложного проекта, а не простенькой тестовой задачки. А так же какие потом будут тёплые чувства в адрес МС, когда по итогам длительного исследования всё же выяснится истинный виновник.
Да, и кстати хочу ещё уточнить, если вдруг кто-то не понял, что проблема то весьма обширная, а не узкоспециализированная на применение функции sin — портится оптимизация любого кода в подобном цикле, а не только для sin. Просто для неё разница в производительности очень сильно бросилась в глаза, что и побудило к расследованию. Но проблема то есть и у банального умножения в таком же цикле, так что это какой-то их глобальный косяк.
И судя по сообщениям на форуме (я сам естественно не проверял) он затрагивает как минимум версии: 2013, 2015, 2017. Так что получаем в итоге весьма показательную картинку... )))
Здравствуйте, Serg27, Вы писали:
S>Я не поленился и сделал bug report — connect.microsoft.com S>Предмет бага — разный уровень оптимизации для очень близкого кода. Посланный код основан на rsdn
S>P.S. S>Хотел бы еще раз отметить, что для этого вырожденного кода включение оптимизации в одном случае дает выигрыш в 27 раз, а в другом в 1.5. При идеальной же оптимизации выигрыш должен был быть в N_MULTIPLY = 1000000 раз. С этим не справился ни один компилятор... S>P.P.S. S>Самого кода пока не видно. Они декларируют задержку в появлении загруженных файлов от нескольких часов до суток.
Твой код некорректен в роли проверки быстродействия — никто тебе не гарантирует инлайн лямбд в таких ситуациях. Я то это использовал для краткости записи (проверив что это никак не влияет на цифры в моём конкретном случае). Но в твоём случае это абсолютно не известно. Далее, у тебя там используется ряд мест потенциально попадающих под разные оптимизации. В общем я бы на месте MS даже не стал бы рассматривать подобную бредятину, т.к. в ней не видно никаких очевидных ошибок. Если уж ты хотел сделать краткий код демонстрирующий суть проблемы, то это должно было бы выглядеть так:
Тут ключевой нюанс не в самих абсолютных цифрах или сравнение компиляторов, а в том, что данная программа собранная компилятором без откровенных багов должна выдавать одинаковые цифры при любых настройках оптимизации.
P.S. Да, при желание можешь заменить outputs[j]=inputs[j]*i; на скажем outputs[j]=inputs[j]*sin(0.1f*i); чтобы получить заявленную дикую разницу в 100 раз. Но это всё равно та же самая проблема, просто на sin она видна особо ярко. )))
Здравствуйте, alex_public, Вы писали:
_>Очень даже можно. ) Так и представил себе увлекательный поиск решения данной проблемы внутри сложного проекта, а не простенькой тестовой задачки. А так же какие потом будут тёплые чувства в адрес МС, когда по итогам длительного исследования всё же выяснится истинный виновник.
Истинный виновник тут, конечно, тот, кто столь сложным кодом заполняет массив константой, известной на момент компиляции...
Нужны какие-то реальные вычисления, то, что компилятор не может выкинуть сам. Ну, например, вычисление знаков числа pi, начиная с задаваемого из командной строки...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
_>1. Я не пользуюсь MSVC, так что заниматься этим делом у меня особо желания нет. ) _>2. Да, багов у компиляторов бывало много (я помню ещё те времена, когда они просто падали от шаблонов большой вложенности). Но тут какой-то особо ненормальный случай: ошибка на совсем банальном коде и он при этом делает вид, что всё корректно скомпилировал (ну и да, формально оно работает).
Вы потратили время на написание в форуме и чтения ответов. Это время превышает время, которое требуется на написание bug репорта. Возможно, время нужное на поиск наименьшего по размеру примера, вызывающего bug, несколько больше. Посмотрите все же на bug трекер любого компилятора (если не любите MS, то хоть gcc, хоть CLang) и Вы увидите самый банальный код, который вызывает проблемы. Правда банальный он из-за усилий bug репортера, который привел код к этой банальщине, чтобы помочь развитию компилятора, а значит себе и другим.
P.S.
Если у Вас проблемы с английским, то сделайте наименьший код, который показывает проблему, и попросите на форуме сделать bug report. Правда английский для этого нужен минимальный и google translate хватит.
P.P.S.
Проблема в вашем коде на первый взгляд связана с векторизацией/оптимизацией циклов (вместо declv_sin вызывается sin). Также применение /fp:fast все улучшает (как очень часто...)
Здравствуйте, alex_public, Вы писали:
_>А ты случаем не путаешь медленные вычисления и замораживание интерфейса при таких вычислениях (естественно в том случае, если это писал криворукий программист)? ))) Потому как от второй проблемы расстановка дополнительных циклов обработки сообщений ещё может помочь, а вот с первой проблемой ничем подобным помочь нельзя. А то бы иначе сейчас все суперкомпьютеры выстроились в очередь за "прокачкой сообщений от ОС"...
Hint: multithreading — это единственное решение данной проблемы в Production.
_>Самое забавное, что ты даже не понял что ты собственно сделал в своём и почему он снова заработал. ) И тебя даже не смущает тот факт, что если заменить цикл обработки сообщений на какой-нибудь cout<<"xaxa"; то всё равно проблема решается.
Sorry, но это ты не понял:
Любой "оконный" вывод в современных графических операционных системах связан с обменом сообщениями операционной системы.
Без них не отработает ничего(ни вывод std::cout на консоль, ни обновление прогресс бара).
В данном случае, этот вывод (за счёт прокачки сообщений реализованной в недрах OS Windows) просто обеспечивал "сторонний эффект".
Только вот тут редкий случай, когда данный "сторонний эффект" действует положительно, а не отрицательно
Когда я явно сделал ту же прокачку — всё вернулось на свои места.
_>Поставь для начала (я использовал не такие, но это самый простой вариант для начальной оценки эффекта) в MinGW опции "-O3 -march=native" — сразу оценишь разницу.
Хорошо, попробую!
_>С таким подходом нельзя даже приближаться к тестам на производительность. И да, дефолтные опции Qt весьма далеки от максимальной эффективности.
Пойми правильно, уважаемый alex_public, что я ведь не собираюсь "с пеной у рта" доказывать, что MSVC — the best
Просто хочу докопаться до истины.
Окажется, что в этом эксперименте оба компилятора примерно одинаковы, или даже MinGW чуть быстрее — милости просим!
Здравствуйте, alex_public, Вы писали: _>Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
Упрощенный пример кода:
#define _USE_MATH_DEFINES
#include <cmath>
#include <time.h>
#include <iostream>
using namespace std;
constexpr auto N_MULTIPLY = 1000000;// 10000000;
constexpr int N_GENERATED = 1000;
double outputs_dbl[N_GENERATED];
template<typename F> void Measure(F f)
{
int i;
for (i = 2; i<N_MULTIPLY; i++) {
for (int j = 0; j<N_GENERATED; j++) f(i, j);
}
// if (i == 0) cout << "msvc";
}
void fun1(int i, int j)
{
outputs_dbl[j%N_GENERATED] = sin((double)i);
}
void fun2(int i, int j)
{
outputs_dbl[j] = sin((double)i);
}
int main()
{
auto start = clock();
Measure(fun1);
auto finish = clock();
double duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "Measure(fun1) - " << duration << " s." << endl;
start = clock();
Measure(fun2);
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "Measure(fun2) - " << duration << " s." << endl;
}
Результат выполнения (intel I5-2520m), VS 2015 update 3. Различные опции оптимизации влияют слабо.
Measure(fun1) — 1.422 s.
Measure(fun2) — 26.15 s.
Если запретить оптимизацию в Release то получится следующее:
Measure(fun1) — 38.862 s.
Measure(fun2) — 38.116 s.
Т.е. оптимизация для fun1 дала выигрыш в 27 раз, а для fun2 в 1,5. Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз, так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
Почему такие небольшие изменения в коде дают такие результаты интересно только разработчикам компилятора.
Конечно для оценки качества генерации компилятора использовать код такого типа нельзя, так как время выполнения может быть от 0 (просто сгенировать нужный массив на этапе компиляции/загрузки) до плохо оптимизированного. Не зря же используют какие-то более реальные задачи со сложным кодом для проверки оптимизации компилятором.
Здравствуйте, Serg27, Вы писали:
S>Я не поленился и сделал bug report — connect.microsoft.com S>Предмет бага — разный уровень оптимизации для очень близкого кода. Посланный код основан на rsdn
Thanks for the great bug report. I looked into the issue, and it turns out that the sin function call in fun1 is being hoisted out of the innermost loop, while that's not happening in the case of fun2. This explains the performance difference.
We will keep looking further into the reasoning and send out an update.
Thanks,
Amit
Возможно поправят оптимизацию, раз баг дошел до разработчика...
Спасибо тем, кто "лайкнул" этот баг у них на сайте — иначе бы вообще руки не дошли.
Здравствуйте, alex_public, Вы писали:
_>Т.е. ты считаешь, что описанное поведение — это не ошибка компилятора, а нормальная ситуация? )))
Ситуация предсказуемая — тяжелые вычисления или выноси в отдельный рабочий поток, или прокачивай сообщения ОС.
Иначе — терпи тормоза
К багам компилятора — это отношения не имеет (от слова совсем).
AG>Можно по-разному относиться к маркетингу/политике "мелкомягких", их модели продаж и т.д. AG>Но в тоже время, следует отдать должное — их продукты очень даже достойные.
_>Если говорить про продукцию для C++, то они были безусловным лидером в данной области целое десятилетие (начиная с середины 90-ых), а потом проспали следующее десятилетие, сделав на .net. Сейчас вроде снова стараются — посмотрим что выйдет в будущем. Но судя по подобным косякам работать там надо ещё очень много.
Тренд на современный C++ (С++11 и C++14) у "мелкомягких" развивается уже примерно 5 лет (с 2012 студии).
А то что ты здесь именуешь "косяками" — просто говорит о твоём малом опыте работы с GUI подсистемой.
Скажем так — прокачка сообщений — это НЕ костыль, а особенность программирования подобных систем.
Здесь рассматривать многопоточность (вынос в рабочий поток) стоит, но только для несколько иных случаев.
Для такого простого случая, тем боле НЕ в Production — ИМХО можно и через прокачку.
_>Даже если забыть про данный косяк... Ты разве не посмотрел на результаты измерений в моём первом сообщение данной темы?
Смотрел и результаты:
a) Меня радует, что эти мои старые тесты кого-то заинтересовали. Также радует, что доработан в современном стиле (те же лямбды);
b) В то же время, меня беспокоит, что "причёсывание" этих тестов вполне может повлиять на конечные результаты;
c) Сами цифры — IMHO зависят сильно от опций оптимизации компиляцией (здесь есть целое поле для разночтений ).
_>Даже в исправленном состояние msvc уступает gcc на данных тестах. Да, там цифры порядка 10%, а не в разы, но тем не менее в пользу gcc. Просто надо было выставить в тесте правильные опции для него, а не использовать дефолтные
Хорошо, на следующей неделе — дополнительно поэкспериментирую с опциями MinGW и MSVC опишу тут результаты.
_>(которые делают не полную оптимизацию и ориентируются на процессоры типа Пентиумов), как судя по цифрам сделал ты.
Пока что — я НЕ выставлял специально никаких опций — это делает Qt Vs Addin и его настройки.
В данном случае я полагался именно на продукт Qt. Есть уверенность, что авторы Qt Vs Addin применяют эффективные настройки и опции компилятора.
Насчёт того, что играя опциями можно ускорить (даже тот же msvc результат) — идея ценная, хорошая (хотя есть ощущение, что Qt уже всё дало на MAX: для всех поддерживаемых ими компиляторов).
_>Кстати, самое забавное, что ты даже и для msvc полноценную оптимизацию использовать не можешь. Потому как судя по цифрам у тебя процессор минимум с avx, а то и с avx2...
+100500
Вполне возможно — это правильный вариант! Спасибо!
Здравствуйте, AlexGin, Вы писали:
_>>Т.е. ты считаешь, что описанное поведение — это не ошибка компилятора, а нормальная ситуация? ))) AG>Ситуация предсказуемая — тяжелые вычисления или выноси в отдельный рабочий поток, или прокачивай сообщения ОС. AG>Иначе — терпи тормоза
А ты случаем не путаешь медленные вычисления и замораживание интерфейса при таких вычислениях (естественно в том случае, если это писал криворукий программист)? ))) Потому как от второй проблемы расстановка дополнительных циклов обработки сообщений ещё может помочь, а вот с первой проблемой ничем подобным помочь нельзя. А то бы иначе сейчас все суперкомпьютеры выстроились в очередь за "прокачкой сообщений от ОС"...
AG>К багам компилятора — это отношения не имеет (от слова совсем).
Самое забавное, что ты даже не понял что ты собственно сделал в своём коде и почему он снова заработал. ) И тебя даже не смущает тот факт, что если заменить цикл обработки сообщений на какой-нибудь cout<<"xaxa"; то всё равно проблема решается.
_>>Даже если забыть про данный косяк... Ты разве не посмотрел на результаты измерений в моём первом сообщение данной темы? AG>Смотрел и результаты: AG>a) Меня радует, что эти мои старые тесты кого-то заинтересовали. Также радует, что доработан в современном стиле (те же лямбды); AG>b) В то же время, меня беспокоит, что "причёсывание" этих тестов вполне может повлиять на конечные результаты; AG>c) Сами цифры — IMHO зависят сильно от опций оптимизации компиляцией (здесь есть целое поле для разночтений ).
Безусловно. Но если мы возьмём настройки дающие максимально возможную производительность на каждом из компиляторов и при этом один из них будет давать чуть более быстрый код, то можно будет сказать, что он эффективнее? )
_>>Даже в исправленном состояние msvc уступает gcc на данных тестах. Да, там цифры порядка 10%, а не в разы, но тем не менее в пользу gcc. Просто надо было выставить в тесте правильные опции для него, а не использовать дефолтные AG>Хорошо, на следующей неделе — дополнительно поэкспериментирую с опциями MinGW и MSVC опишу тут результаты.
Поставь для начала (я использовал не такие, но это самый простой вариант для начальной оценки эффекта) в MinGW опции "-O3 -march=native" — сразу оценишь разницу. )))
_>>(которые делают не полную оптимизацию и ориентируются на процессоры типа Пентиумов), как судя по цифрам сделал ты. AG>Пока что — я НЕ выставлял специально никаких опций — это делает Qt Vs Addin и его настройки. AG>В данном случае я полагался именно на продукт Qt. Есть уверенность, что авторы Qt Vs Addin применяют эффективные настройки и опции компилятора.
С таким подходом нельзя даже приближаться к тестам на производительность. И да, дефолтные опции Qt весьма далеки от максимальной эффективности.
Здравствуйте, AlexGin, Вы писали:
_>>А ты случаем не путаешь медленные вычисления и замораживание интерфейса при таких вычислениях (естественно в том случае, если это писал криворукий программист)? ))) Потому как от второй проблемы расстановка дополнительных циклов обработки сообщений ещё может помочь, а вот с первой проблемой ничем подобным помочь нельзя. А то бы иначе сейчас все суперкомпьютеры выстроились в очередь за "прокачкой сообщений от ОС"... AG>Hint: multithreading — это единственное решение данной проблемы в Production.
Ну давай, перепиши свой пример, чтобы у тебя вычисления шли в отдельном потоке и посмотрим на твой шок от результата.
_>>Самое забавное, что ты даже не понял что ты собственно сделал в своём и почему он снова заработал. ) И тебя даже не смущает тот факт, что если заменить цикл обработки сообщений на какой-нибудь cout<<"xaxa"; то всё равно проблема решается. AG>Sorry, но это ты не понял: AG>Любой "оконный" вывод в современных графических операционных системах связан с обменом сообщениями операционной системы. AG>Без них не отработает ничего(ни вывод std::cout на консоль, ни обновление прогресс бара). AG>В данном случае, этот вывод (за счёт прокачки сообщений реализованной в недрах OS Windows) просто обеспечивал "сторонний эффект". AG>Только вот тут редкий случай, когда данный "сторонний эффект" действует положительно, а не отрицательно AG>Когда я явно сделал ту же прокачку — всё вернулось на свои места.
Я даже оставлю без комментариев очаровательную теорию о том, что cout работает через очередь сообщений винды и попробую всё же воззвать к элементарной логике. А тебя совсем не смущает, что в моём коде (но если ты заменишь в своём коде свой "цикл сообщений" на данную строчку, то всё аналогично нормально заработает) используется строчка if(i==0) cout<<"msvc????????????????????"; т.е. данный cout не выполняется никогда! Но при этом он почему-то ускоряет исполнение кода в 100 раз...
_>>С таким подходом нельзя даже приближаться к тестам на производительность. И да, дефолтные опции Qt весьма далеки от максимальной эффективности. AG> AG>Пойми правильно, уважаемый alex_public, что я ведь не собираюсь "с пеной у рта" доказывать, что MSVC — the best AG>Просто хочу докопаться до истины. AG>Окажется, что в этом эксперименте оба компилятора примерно одинаковы, или даже MinGW чуть быстрее — милости просим!
Ну вот реальные результаты (без учёта багов msvc) для данного кода на максимальных настройках оптимизации ты можешь посмотреть в моём первом сообщение в данной теме под названием "результат2". В зависимости от целевой архитектуры процессора и конкретного теста результаты разные, но в среднем я бы сказал что gcc чуть лучше. Хотя для подавляющего большинства ПО можно считать что разницы нет вообще (опять же если без учёта багов msvc).
Здравствуйте, AlexGin, Вы писали:
AG>2) В то же время, Вы уважаемый alex_public, пытаетесь "навесить ярлык" на прекрасный программный продукт от Microsoft. AG>Это, к сожалению, НЕ делает Вам, уважаемый alex_public, чести
Т.е. ты считаешь, что описанное поведение — это не ошибка компилятора, а нормальная ситуация? )))
AG>Можно по-разному относиться к маркетингу/политике "мелкомягких", их модели продаж и т.д. AG>Но в тоже время, следует отдать должное — их продукты очень даже достойные.
Если говорить про продукцию для C++, то они были безусловным лидером в данной области целое десятилетие (начиная с середины 90-ых), а потом проспали следующее десятилетие, сделав ставку на .net. Сейчас вроде снова стараются — посмотрим что выйдет в будущем. Но судя по подобным косякам работать там надо ещё очень много.
AG>3) Игра опциями настройки компилятора, как бы ими не играть, не позволят серьезно изменить соотношение — т.е. AG>для Windows систем — (хотим мы это признавать или нет) MS компилятор окажется быстрее конкурента. AG>Ларчик открывается очень просто: AG>http://rsdn.org/forum/cpp/6723069.1
Даже если забыть про данный косяк... Ты разве не посмотрел на результаты измерений в моём первом сообщение данной темы? Даже в исправленном состояние msvc уступает gcc на данных тестах. Да, там цифры порядка 10%, а не в разы, но тем не менее в пользу gcc. Просто надо было выставить в тесте правильные опции для него, а не использовать дефолтные (которые делают не полную оптимизацию и ориентируются на процессоры типа Пентиумов), как судя по цифрам сделал ты.
Кстати, самое забавное, что ты даже и для msvc полноценную оптимизацию использовать не можешь. Потому как судя по цифрам у тебя процессор минимум с avx, а то и с avx2, но ты это у себя никак не использовал, получая даже от msvc производительность в разы хуже возможной.
Здравствуйте, LaptevVV, Вы писали:
LVV>1. Необходимо видеть настройки компилятора микрософта.
Флаги такие: -EHsc -Za -O2 -arch:AVX2.
LVV>2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим. LVV>Интересно было бы сравнить производительность 64-битных приложений. LVV>Хотя бы и на тех же тестах.
Там всё тоже самое) Я на самом деле параллельно проверял (у меня просто bat файл генерирующий и запускающий все возможные варианты), только не опубликовал эти результаты, чтобы не захламлять сообщение.
Здравствуйте, Serg27, Вы писали: S>Упрощенный пример кода: S>Т.е. оптимизация для fun1 дала выигрыш в 27 раз, а для fun2 в 1,5. Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз, так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
Для полноты картины:
тесты VS2008 и VS2010
Celeron J1900 Win7 x64
Visual Studio 2008 SP1 X86
Release /O1 Measure(fun1) — 103.994 s. Measure(fun2) — 92.975 s. (with cout "msvc")
Release /O1 Measure(fun1) — 103.994 s. Measure(fun2) — 92.975 s. (w/o cout "msvc")
Release /O2 Measure(fun1) — 94.713 s. Measure(fun2) — 90.441 s. (with cout "msvc")
Release /O2 Measure(fun1) — 5.112 s. Measure(fun2) — 1.783 s. (w/o cout "msvc")
Visual Studio 2008 SP1 X64
Release /O1 Measure(fun1) — 99.476 s. Measure(fun2) — 95.706 s. (with cout "msvc")
Release /O1 Measure(fun1) — 4.503 s. Measure(fun2) — 0.357 s. (w/o cout "msvc")
Release /O2 Measure(fun1) — 3.54 s. Measure(fun2) — 0.645 s. (with cout "msvc")
Release /O2 Measure(fun1) — 3.69 s. Measure(fun2) — 0.637 s. (w/o cout "msvc")
Visual Studio 2010 SP1 X86
Release /O1 Measure(fun1) — 104.399 s. Measure(fun2) — 92.204 s. (with cout "msvc")
Release /O1 Measure(fun1) — 103.797 s. Measure(fun2) — 93.03 s. (w/o cout "msvc")
Release /O2 Measure(fun1) — 5.118 s. Measure(fun2) — 1.787 s. (with cout "msvc")
Release /O2 Measure(fun1) — 5.152 s. Measure(fun2) — 1.818 s. (w/o cout "msvc")
Здравствуйте, Serg27, Вы писали:
S>Я не поленился и сделал bug report — connect.microsoft.com
Мне говорили — там аттачи больше года не работают. Не появятся через день — смело вставляй ссылку.
Здравствуйте, AlexGin, Вы писали:
AG>3) Игра опциями настройки компилятора, как бы ими не играть, не позволят серьезно изменить соотношение — т.е. AG>для Windows систем — (хотим мы это признавать или нет) MS компилятор окажется быстрее конкурента.
сказал правильно — налицо баг компилятора, бывает . есть обходной путь — хорошо.
AG>Ларчик открывается очень просто: AG>http://rsdn.org/forum/cpp/6723069.1
а это тот самый обходной путь, причем у ТС он гораздо проще — у него "мертвая" ветка кода, которая все равно попадает в asm и влияет на кодогенерацию.
Здравствуйте, Serg27, Вы писали: S>После того как я послал bug report в MS, я решил проверить, а как справляется с этим вырожденным примером CLang (по мнению многих лучший компилятор нашего времени). Так как toolset Clang установлен у меня в VS2015, то это делается переключением toolset в настройках проекта. S>
S> S>Вывод в стиле ТС :)) S>!!!Как видно Clang уступает MSVC и вообще не пригоден к использованию!!!! S>
Вообще то как раз твой тест показывает, что Clang нет никаких подобных ошибок — он для обоих вариантов кода выдаёт одинаковый результат. Почему такие абсолютные цифры — это отдельный вопрос (например там не произошёл инлайн лямбд, который тебе никто не гарантировал), с которым ты можешь поразбираться при желание. Но данной ошибки в Clang нет. В отличие от продукта MS. )))
Здравствуйте, alex_public, Вы писали:
_>На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
У компиляторов множество флагов оптимизации. Производительность gcc у сборки debug и release сильно отличаются. А уж если углубляться внутрь настроек, то получим и того больше. Можно так же посмотреть промежуточный результат одной из стадий компиляции, то есть программу на ассемблере.
То есть возможно компилятор от майкрософт был плохо настроен, да и из mingw не факт, что нельзя было вытянуть больше. Впрочем чего это я, сам то пользуюсь gcc. Будем "объективными" — майкрософт говно.
Здравствуйте, velkin, Вы писали:
_>>На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию. V>У компиляторов множество флагов оптимизации. Производительность gcc у сборки debug и release сильно отличаются. А уж если углубляться внутрь настроек, то получим и того больше. Можно так же посмотреть промежуточный результат одной из стадий компиляции, то есть программу на ассемблере. V>То есть возможно компилятор от майкрософт был плохо настроен, да и из mingw не факт, что нельзя было вытянуть больше. Впрочем чего это я, сам то пользуюсь gcc. Будем "объективными" — майкрософт говно.
В данном тесте оба компилятора очевидно были сконфигурированы на максимальную производительность. Как раз теми самыми множествами флагов оптимизации. )))
Но даже если бы он и был недостаточно хорошо настроен... Это никак не могло бы оправдать замедление кода более чем в 100 раз (даже если почему-то тупо отключаются все SIMD оптимизации, то это максимум в несколько раз может изменить быстродействие) при незначительных изменения кода (никак не влияющих на быстродействие). Это вообще вопрос из другой области — не из настроек, а из багов.
1. Необходимо видеть настройки компилятора микрософта.
2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим.
Интересно было бы сравнить производительность 64-битных приложений.
Хотя бы и на тех же тестах.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>1. Необходимо видеть настройки компилятора микрософта. LVV>2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим. LVV>Интересно было бы сравнить производительность 64-битных приложений. LVV>Хотя бы и на тех же тестах.
На 64 битах результат подтверждаю.
LVV>>1. Необходимо видеть настройки компилятора микрософта. LVV>>2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим. LVV>>Интересно было бы сравнить производительность 64-битных приложений. LVV>>Хотя бы и на тех же тестах. S>На 64 битах результат подтверждаю.
В смысле — в 100 раз хуже gcc?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>>>1. Необходимо видеть настройки компилятора микрософта. LVV>>>2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим. LVV>>>Интересно было бы сравнить производительность 64-битных приложений. LVV>>>Хотя бы и на тех же тестах. S>>На 64 битах результат подтверждаю. LVV>В смысле — в 100 раз хуже gcc?
Все как у ТС (с точностью до железа). Запускал из VS 2015 update 3. Release x64 — стандартные установки. Это bug и bug скорее всего коде-генератора.
забавное сообщение, на которое я собирался ответить прямо там в темке, отметив что не стоит браться за тесты производительности тем, кто не может выставить правильные опции компиляторам, а пользуется только дефолтными (а они очень разные у разных компиляторов). Однако перед написанием ответа я решил всё же установить компилятор от MS, чтобы удостовериться, что за прошедшее время ничего не изменилось и он по прежнему слабенький, как я и говорил. Но в процессе этого теста вылезло ТАКОЕ, что я сразу же забыл об изначальной дискуссии и решил написать отдельное сообщение про это.
Здравствуйте, Serg27, Вы писали:
_>>Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию. S>Такое ощущение, что Вы в первый раз в жизни увидели ошибку компилятора... S>Как поступают профессионалы: S>1) Сокращают код до необходимого минимума и посылают bug репорт производителю. Для компилятора от MS это https://connect.microsoft.com/VisualStudio S>2) Если очень хочется поделиться о баге на форуме, то даете ссылку на bug report и (так поступают настоящие профи) делаете ассемблерный листинг и показываете сообществу где именно облажался компилятор. На RSDN это можно регулярно встретить.
1. Я не пользуюсь MSVC, так что заниматься этим делом у меня особо желания нет. )
2. Да, багов у компиляторов бывало много (я помню ещё те времена, когда они просто падали от шаблонов большой вложенности). Но тут какой-то особо ненормальный случай: ошибка на совсем банальном коде и он при этом делает вид, что всё корректно скомпилировал (ну и да, формально оно работает).
S>P.S. S>если Вы полазите по bug трекеру любого компилятора, то увидете множество удивительных примеров кода, в которых компилятор лажается. Очень поучительно, чтобы не давать заголовки, которые Вы дали вашему сообщению, и потерять веру в безгрешность компиляторов.
Так как раз заголовок в точном соответствие с данным тезисом: "шедевр" то очередной, а не первый. )))
Здравствуйте, T4r4sB, Вы писали:
TB>А в ассемблерном коде что там происходит?
На самом деле в данном случае можно даже не смотреть в ассемблер, чтобы понять происходящее. Достаточно собрать программку с динамическими библиотеками и посмотреть на списки импорта: у криво работающей в списках присутствует "sin", а у нормально работающей нет. ) Это так сказать объяснение диких цифр. А вот причина такого поведения (ведь там портится код и не только с sin, просто это не так чувствуется) по прежнему загадочна и известна только разработчикам данного продукта.
Здравствуйте, pilgrim_, Вы писали:
_>В 1-м случае синус вычисляется на каждой итерации вложенного цикла (call sin), во 2-м случае вычисление синуса вынесено на верхний цикл (call __vdecl_sin2). _>Что характерно в обоих вариантах используются разные реализации синуса, которые как пишут дают разный результат
А это точно итоговый код?
Условие (i==0) никогда не выполняется.
Его не должно быть в итоговом коде, а проверка там есть.
Здравствуйте, Serg27, Вы писали:
S>Вы потратили время на написание в форуме и чтения ответов. Это время превышает время, которое требуется на написание bug репорта. Возможно, время нужное на поиск наименьшего по размеру примера, вызывающего bug, несколько больше. Посмотрите все же на bug трекер любого компилятора (если не любите MS, то хоть gcc, хоть CLang) и Вы увидите самый банальный код, который вызывает проблемы. Правда банальный он из-за усилий bug репортера, который привел код к этой банальщине, чтобы помочь развитию компилятора, а значит себе и другим.
Так, поясню ещё раз, более просто: у меня нет никакого желания улучшать работу MSVC, а вот желание пообщаться с коллегами по форуму у меня есть. )
S>P.P.S. S>Проблема в вашем коде на первый взгляд связана с векторизацией/оптимизацией циклов (вместо declv_sin вызывается sin).
Это очевидно.
S>Также применение /fp:fast все улучшает (как очень часто...)
А вот здесь не верно. Во-первых применять /fp:fast просто так нельзя — это меняет результат вычислений и подходит далеко не для всех случаев. А во-вторых в данном конкретном случае это вообще ни на что не влияет, ни на быстродействие работающего кода, ни на исправление ошибки.
Здравствуйте, rus blood, Вы писали:
RB>А это точно итоговый код? RB>Условие (i==0) никогда не выполняется. RB>Его не должно быть в итоговом коде, а проверка там есть.
Проверил локально, удивительно, для /O2 (для /Ox аналогично), но походу да:
x64
cl /O2 /DNDEBUG fast.cpp -o fast.exe /FA
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23918 for x64
$LL4@Measure:
; Line 22
movd xmm0, edi
pshufd xmm0, xmm0, 0
paddd xmm0, xmm0
cvtdq2pd xmm0, xmm0
mulpd xmm0, xmm7
call __vdecl_sin2
xor eax, eax
mov ecx, 500 ; 000001f4H
npad 15
$LL7@Measure:
movups xmm1, XMMWORD PTR ?randoms_dbl@@3PANA[rax+rbp]
addpd xmm1, xmm0
addpd xmm1, xmm6
movups XMMWORD PTR ?outputs_dbl@@3PANA[rax+rbp], xmm1
add rax, 16
sub rcx, 1
jne SHORT $LL7@Measure
; Line 23
test edi, edijne SHORT $LN2@Measure
lea rdx, OFFSET FLAT:??_C@_0BJ@JOJDFEDH@msvc?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$DP?$AA@
lea rcx, OFFSET FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A ; std::cout
call ??$?6U?$char_traits@D@std@@@std@@YAAEAV?$basic_ostream@DU?$char_traits@D@std@@@0@AEAV10@PEBD@Z ; std::operator<<<std::char_traits<char> >
$LN2@Measure:
; Line 21
inc edi
cmp edi, 100000 ; 000186a0H
jl SHORT $LL4@Measure
x86
Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23918 for x86
1) Выражаю большую признательность к моим тестам производительности, которые я поднял из моих архивов и опубликовал на GitHub-е,
специально для оценки различных компиляторов: MSVC и MinGW.
2) В то же время, Вы уважаемый alex_public, пытаетесь "навесить ярлык" на прекрасный программный продукт от Microsoft.
Это, к сожалению, НЕ делает Вам, уважаемый alex_public, чести
Можно по-разному относиться к маркетингу/политике "мелкомягких", их модели продаж и т.д.
Но в тоже время, следует отдать должное — их продукты очень даже достойные.
3) Игра опциями настройки компилятора, как бы ими не играть, не позволят серьезно изменить соотношение — т.е. для Windows систем — (хотим мы это признавать или нет) MS компилятор окажется быстрее конкурента.
Здравствуйте, acDev, Вы писали: D>Для полноты картины: D>
тесты VS2008 и VS2010
D>Celeron J1900 Win7 x64
D>Visual Studio 2008 SP1 X86 D>Release /O1 Measure(fun1) — 103.994 s. Measure(fun2) — 92.975 s. (with cout "msvc") D>Release /O1 Measure(fun1) — 103.994 s. Measure(fun2) — 92.975 s. (w/o cout "msvc") D>Release /O2 Measure(fun1) — 94.713 s. Measure(fun2) — 90.441 s. (with cout "msvc") D>Release /O2 Measure(fun1) — 5.112 s. Measure(fun2) — 1.783 s. (w/o cout "msvc")
D>Visual Studio 2008 SP1 X64 D>Release /O1 Measure(fun1) — 99.476 s. Measure(fun2) — 95.706 s. (with cout "msvc") D>Release /O1 Measure(fun1) — 4.503 s. Measure(fun2) — 0.357 s. (w/o cout "msvc") D>Release /O2 Measure(fun1) — 3.54 s. Measure(fun2) — 0.645 s. (with cout "msvc") D>Release /O2 Measure(fun1) — 3.69 s. Measure(fun2) — 0.637 s. (w/o cout "msvc")
D>Visual Studio 2010 SP1 X86 D>Release /O1 Measure(fun1) — 104.399 s. Measure(fun2) — 92.204 s. (with cout "msvc") D>Release /O1 Measure(fun1) — 103.797 s. Measure(fun2) — 93.03 s. (w/o cout "msvc") D>Release /O2 Measure(fun1) — 5.118 s. Measure(fun2) — 1.787 s. (with cout "msvc") D>Release /O2 Measure(fun1) — 5.152 s. Measure(fun2) — 1.818 s. (w/o cout "msvc")
В 2008 и 2010 версиях данной ошибки похоже нет. И да, в данном коде от Serg27 не требуется раскомментировать строку с cout (её вообще можно убрать оттуда), т.к. в его варианте func1 уже является аналогом моего кода с раскоментированным cout, а func2 является аналогом кода с закомментированным.
Здравствуйте, Erop, Вы писали:
_E>Истинный виновник тут, конечно, тот, кто столь сложным кодом заполняет массив константой, известной на момент компиляции... E>Нужны какие-то реальные вычисления, то, что компилятор не может выкинуть сам. Ну, например, вычисление знаков числа pi, начиная с задаваемого из командной строки...
Тесты конечно достаточно сомнительные. Но того, что ты упомянул, я в них что-то не вижу. Где там по твоему заполнение массива константой известной на момент компиляции?
Здравствуйте, Erop, Вы писали:
E>Истинный виновник тут, конечно, тот, кто столь сложным заполняет массив константой, известной на момент компиляции...
Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу.
E>Нужны какие-то реальные вычисления, то, что компилятор не может выкинуть сам. Ну, например, вычисление знаков числа pi, начиная с задаваемого из командной строки...
Тоже один из вариантов...
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, Erop, Вы писали:
E>>Истинный виновник тут, конечно, тот, кто столь сложным заполняет массив константой, известной на момент компиляции... AG>Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу
Егор абсолютно прав. Посмотрите код внимательно. Там где "Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу" проблем нет (это в коде ТС). В моем коде оставлено только два варианта с одинаковым результатом вычислений, причем результат мог быть вычислен во время компиляции. цитата:
Т.е. оптимизация для fun1 дала выигрыш в 27 раз, а для fun2 в 1,5. Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз, так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
Напомню, что N_MULTIPLY = 1000000. Т.е gcc тоже облажался с оптимизацией... Причем очень сильно...
Здравствуйте, Serg27, Вы писали:
S>Здравствуйте, AlexGin, Вы писали:
AG>>Здравствуйте, Erop, Вы писали:
E>>>Истинный виновник тут, конечно, тот, кто столь сложным заполняет массив константой, известной на момент компиляции... AG>>Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу S>Егор абсолютно прав. Посмотрите внимательно. Там где "Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу" проблем нет (это в ТС). В моем коде оставлено только два варианта с одинаковым результатом вычислений, причем результат мог быть вычислен во время компиляции. цитата: S>
S>Т.е. оптимизация для fun1 дала выигрыш в 27 раз, а для fun2 в 1,5. Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз, так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
S>Напомню, что N_MULTIPLY = 1000000. Т.е gcc тоже облажался с оптимизацией... Причем очень сильно...
Вообще-то в моём случае:
const int N_MULTIPLY = 10000000;
То есть десять миллионов, вы уважаемый Serg27, почему-то эту константу приняли на порядок меньше.
Здравствуйте, Serg27, Вы писали:
S>После того как я послал bug report в MS, я решил проверить, а как справляется с этим вырожденным примером CLang (по мнению многих лучший компилятор нашего времени).
Он хороший компилятор с точки зрения сообщений об ошибках в сложном c++ коде,
плюс исходники у него намного лучше читаются по сравнению с gcc,
больше честно говоря на моих проектах я плюсов не заметил,
хотя то, что они за столь короткое время настигли остальные компилятор,
помоему это огромное достижение,
но тем не менее для пузомерок на x86/amd64 всегда впереди всех был компилятор от Intel, разве нет?
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, alex_public, Вы писали:
_>>А ты случаем не путаешь медленные вычисления и замораживание интерфейса при таких вычислениях (естественно в том случае, если это писал криворукий программист)? ))) Потому как от второй проблемы расстановка дополнительных циклов обработки сообщений ещё может помочь, а вот с первой проблемой ничем подобным помочь нельзя. А то бы иначе сейчас все суперкомпьютеры выстроились в очередь за "прокачкой сообщений от ОС"... AG>Hint: multithreading — это единственное решение данной проблемы в Production.
_>>Самое забавное, что ты даже не понял что ты собственно сделал в своём и почему он снова заработал. ) И тебя даже не смущает тот факт, что если заменить цикл обработки сообщений на какой-нибудь cout<<"xaxa"; то всё равно проблема решается.
AG>Sorry, но это ты не понял: AG>Любой "оконный" вывод в современных графических операционных системах связан с обменом сообщениями операционной системы. AG>Без них не отработает ничего(ни вывод std::cout на консоль, ни обновление прогресс бара). AG>В данном случае, этот вывод (за счёт прокачки сообщений реализованной в недрах OS Windows) просто обеспечивал "сторонний эффект". AG>Только вот тут редкий случай, когда данный "сторонний эффект" действует положительно, а не отрицательно AG>Когда я явно сделал ту же прокачку — всё вернулось на свои места.
Весьма странная точка зрения.
Определимся с помощью чего мы делаем замеры, с помощью абсолютного времени или каким-то
образом замеряем время которое дала ОС данному потоку.
Во втором случае очевидно никакие системные/библиотечные вызовы в сторону улучшения показателей влиять не могут,
т.к. либо они увеличивают общее время, если не происходит в процессе их вызова переключение потока,
либо никак не учитываются при расчете времени работы, но косвенно должны ухудшать показатели,
за счет забивания всевозможны кэшей своими данными.
В первом случае (случае учета абсолютного времени) системные вызовы теоритически могут влиять,
т.к. ОС в целях улучшения видимой пользователем latency может чуть уменшать или увеличивать
квант времени приложению, и по какой-то причине может решить что приложение с вызовом ProcessMessages
это приложение с которым работает пользователь, а без этого вызова — background process, у которого
можно динамический приоритет планировщика потоков понизить.
Но разве не стоит просто забить на "первый вариант" и не учитывать при benchmarks?
AlexGin:
AG>3) Игра опциями настройки компилятора, как бы ими не играть, не позволят серьезно изменить соотношение — т.е. AG>для Windows систем — (хотим мы это признавать или нет) MS компилятор окажется быстрее конкурента.
При использовании -flto в MinGW у меня везде показывается нулевое время (видимо, из-за того, что из заполняемых массивов никто ничего не читает)
Здравствуйте, Serg27, Вы писали:
E>>>Истинный виновник тут, конечно, тот, кто столь сложным заполняет массив константой, известной на момент компиляции... AG>>Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу S>Егор абсолютно прав. Посмотрите код внимательно. Там где "Массив заполняется случайными значениями, перемноженными на индекс прохода по циклу" проблем нет (это в коде ТС).
Вообще то есть.
S>В моем коде оставлено только два варианта с одинаковым результатом вычислений, причем результат мог быть вычислен во время компиляции. цитата: S>
S>Т.е. оптимизация для fun1 дала выигрыш в 27 раз, а для fun2 в 1,5. Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз, так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
S>Напомню, что N_MULTIPLY = 1000000. Т.е gcc тоже облажался с оптимизацией... Причем очень сильно...
А причём тут вообще gcc? Ты запускал свой код на нём? Если же ты говоришь про изначальный тест, то там нигде нет заполнения массива известными на момент компиляции значениями.
Здравствуйте, alex_public, Вы писали:
_>Я даже оставлю без комментариев очаровательную теорию о том, что cout работает через очередь сообщений винды и попробую всё же воззвать к элементарной логике. А тебя совсем не смущает, что в моём коде (но если ты заменишь в своём коде свой "цикл сообщений" на данную строчку, то всё аналогично нормально заработает) используется строчка if(i==0) cout<<"msvc????????????????????"; т.е. данный cout не выполняется никогда! Но при этом он почему-то ускоряет исполнение кода в 100 раз...
Да, есть проблема — bug компилятора MSVC. Этот баг связан с кодогенерацией при оптимизации.
AG>> AG>>Пойми правильно, уважаемый alex_public, что я ведь не собираюсь "с пеной у рта" доказывать, что MSVC — the best AG>>Просто хочу докопаться до истины. AG>>Окажется, что в этом эксперименте оба компилятора примерно одинаковы, или даже MinGW чуть быстрее — милости просим!
_>Ну вот реальные результаты (без учёта багов msvc) для данного кода на максимальных настройках оптимизации ты можешь посмотреть в моём первом сообщение в данной теме под названием "результат2". В зависимости от целевой архитектуры процессора и конкретного теста результаты разные, но в среднем я бы сказал что gcc чуть лучше. Хотя для подавляющего большинства ПО можно считать что разницы нет вообще (опять же если без учёта багов msvc).
Вполне возможно, что результаты тестов примерно одинаковые. Возможно даже, что MinGW чуть эффективнее.
Почему же тогда первоначальный тест (на Qt) давал такие разные результаты, с явным преимуществом MSVC. Будем посмотреть
Здравствуйте, AlexGin, Вы писали:
_>>Ну вот реальные результаты (без учёта багов msvc) для данного кода на максимальных настройках оптимизации ты можешь посмотреть в моём первом сообщение в данной теме под названием "результат2". В зависимости от целевой архитектуры процессора и конкретного теста результаты разные, но в среднем я бы сказал что gcc чуть лучше. Хотя для подавляющего большинства ПО можно считать что разницы нет вообще (опять же если без учёта багов msvc). AG>Вполне возможно, что результаты тестов примерно одинаковые. Возможно даже, что MinGW чуть эффективнее. AG>Почему же тогда первоначальный тест (на Qt) давал такие разные результаты, с явным преимуществом MSVC. Будем посмотреть
Потому что ты использовал дефолтные (с которыми собрана сама библиотека, но это не значит что надо их использовать для своего приложения) настройки Qt для компилятора, а не свои. Для msvc у них там почти максимальные настройки — разве что только avx не используется. А для gcc там используется во-первых не полная оптимизация (-O2, а не -O3), а во-вторых скорее всего не используется даже просто sse (у компилятора msvc это режим по умолчанию, а у gcc такие вещи надо указывать руками и я не помню указано ли подобное при дефолтной сборке Qt).
Кстати, я вот предпочитаю и саму Qt использовать своей сборки, со своими опциями. Но это так, уже тема отдельного разговора. )))
Здравствуйте, fddima, Вы писали:
F> Мне говорили — там аттачи больше года не работают. Не появятся через день — смело вставляй ссылку.
А вот вам и высокоуровневая оптимизация: аттач приаттачил, написали в окошке, что мол будьте терпеливы — они появятся потом, потому что кеширование и валидация бла бла бла! И в /dev/null их, в /dev/null.
void fun1(unsigned i, unsigned j) {
outputs_dbl[j+0-0] = sin((double)i);
}
Причем, outputs_dbl[j+0] или outputs_dbl[j-0] эффекта не дает, надо именно j+0-0.
От опций /O2 или /Ox поведение не зависит, зависит только от отсутствия /Os.
В случае j+0 синус вызывается на каждом шаге, а в случае j+0-0 — только по внешнему циклу.
S>Глядя на код, оптимизация конечно должна была быть в N_MULTIPLY раз
Чего это?
sin(x) считается на регистрах, а результат надо 1000 раз положить в массив длиной 8 млн байт.
Тут уже скорость записи в ОП сказывается.
S>так результат работы кода — заполненный массив outputs_dbl значением sin(N_MULTIPLY). Но по каким-то соображениям компилятор этого не сделал.
Наверно потому, что sin не является intrinsics.
Это честная библиотечная ф-ия, которая честно линкуется.
Здравствуйте, alex_public, Вы писали:
_>Эти результаты меня уже ничем не удивили — всё как я и предполагал, gcc быстрее, но на небольшие проценты.
_>Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
Здравствуйте, Serg27, Вы писали:
S>Возможно поправят оптимизацию, раз баг дошел до разработчика... S>Спасибо тем, кто "лайкнул" этот баг у них на сайте — иначе бы вообще руки не дошли.