забавное сообщение, на которое я собирался ответить прямо там в темке, отметив что не стоит браться за тесты производительности тем, кто не может выставить правильные опции компиляторам, а пользуется только дефолтными (а они очень разные у разных компиляторов). Однако перед написанием ответа я решил всё же установить компилятор от 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-ёх битного кода.
Здравствуйте, 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-битных приложений.
Хотя бы и на тех же тестах.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, alex_public, Вы писали:
_>Но на фоне открывшейся чудесной "особенности" компилятора от MS данные проценты производительности уже перестают иметь какое-либо значение. На мой взгляд компилятор способный по не объяснимым причинам замедлить исполнение куска кода более чем в 100 раз вообще не может быть пригоден к использованию.
Такое ощущение, что Вы в первый раз в жизни увидели ошибку компилятора...
Как поступают профессионалы:
1) Сокращают код до необходимого минимума и посылают bug репорт производителю. Для компилятора от MS это https://connect.microsoft.com/VisualStudio
2) Если очень хочется поделиться о баге на форуме, то даете ссылку на bug report и (так поступают настоящие профи) делаете ассемблерный листинг и показываете сообществу где именно облажался компилятор. На RSDN это можно регулярно встретить.
P.S.
если Вы полазите по bug трекеру любого компилятора, то увидете множество удивительных примеров кода, в которых компилятор лажается. Очень поучительно, чтобы не давать заголовки, которые Вы дали вашему сообщению, и потерять веру в безгрешность компиляторов.
Здравствуйте, 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, чтобы удостовериться, что за прошедшее время ничего не изменилось и он по прежнему слабенький, как я и говорил. Но в процессе этого теста вылезло ТАКОЕ, что я сразу же забыл об изначальной дискуссии и решил написать отдельное сообщение про это.
Здравствуйте, LaptevVV, Вы писали:
LVV>1. Необходимо видеть настройки компилятора микрософта.
Флаги такие: -EHsc -Za -O2 -arch:AVX2.
LVV>2. Где-то я мельком слышал, что MS некоторое время назад забила на 32-битный режим в компиляторе и все силы бросила на 64-битный режим. LVV>Интересно было бы сравнить производительность 64-битных приложений. LVV>Хотя бы и на тех же тестах.
Там всё тоже самое) Я на самом деле параллельно проверял (у меня просто bat файл генерирующий и запускающий все возможные варианты), только не опубликовал эти результаты, чтобы не захламлять сообщение.
Здравствуйте, 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, просто это не так чувствуется) по прежнему загадочна и известна только разработчикам данного продукта.
В 1-м случае синус вычисляется на каждой итерации вложенного цикла (call sin), во 2-м случае вычисление синуса вынесено на верхний цикл (call __vdecl_sin2).
Что характерно в обоих вариантах используются разные реализации синуса, которые как пишут дают разный результат
_>1. Я не пользуюсь MSVC, так что заниматься этим делом у меня особо желания нет. ) _>2. Да, багов у компиляторов бывало много (я помню ещё те времена, когда они просто падали от шаблонов большой вложенности). Но тут какой-то особо ненормальный случай: ошибка на совсем банальном коде и он при этом делает вид, что всё корректно скомпилировал (ну и да, формально оно работает).
Вы потратили время на написание в форуме и чтения ответов. Это время превышает время, которое требуется на написание bug репорта. Возможно, время нужное на поиск наименьшего по размеру примера, вызывающего bug, несколько больше. Посмотрите все же на bug трекер любого компилятора (если не любите MS, то хоть gcc, хоть CLang) и Вы увидите самый банальный код, который вызывает проблемы. Правда банальный он из-за усилий bug репортера, который привел код к этой банальщине, чтобы помочь развитию компилятора, а значит себе и другим.
P.S.
Если у Вас проблемы с английским, то сделайте наименьший код, который показывает проблему, и попросите на форуме сделать bug report. Правда английский для этого нужен минимальный и google translate хватит.
P.P.S.
Проблема в вашем коде на первый взгляд связана с векторизацией/оптимизацией циклов (вместо declv_sin вызывается sin). Также применение /fp:fast все улучшает (как очень часто...)
Здравствуйте, 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
Здравствуйте, alex_public, Вы писали: _>Так, поясню ещё раз, более просто: у меня нет никакого желания улучшать работу MSVC, а вот желание пообщаться с коллегами по форуму у меня есть. )
Offtop
Ну я тоже поясню в последний раз. Я не посягаю на Ваши желания. Но Ваш экзальтированный тон текста напомнил мне — "я бежала за Вами 2 часа, чтобы сказать, что Вы мне безразличны" (с). Случай же с багом совершенно рутинный, а тут было столько экспрессии ("шедевр", "ТАКОЕ" и т.п.). Я попытался рассказать Вам, как сделать это более профессионально. Примеры на форуме есть. В общем-то ничего личного и надеюсь не обидел/задел.