Очередной "шедевр" от MS
От: alex_public  
Дата: 11.03.17 07:47
Оценка: 53 (9) +1 -1
Краткая предыстория. Изначально было такое http://rsdn.org/forum/cpp/6721686.1
Автор: AlexGin
Дата: 10.03.17
забавное сообщение, на которое я собирался ответить прямо там в темке, отметив что не стоит браться за тесты производительности тем, кто не может выставить правильные опции компиляторам, а пользуется только дефолтными (а они очень разные у разных компиляторов). Однако перед написанием ответа я решил всё же установить компилятор от 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;
    });
}

Так вот запустив этот код (правда тогда в нём не было закомментированной строки) я получил такой замечательный результат:
  результат1
>gcc32-sse
1425 ms.
1985 ms.
3007 ms.

>gcc32-avx
1422 ms.
1115 ms.
1675 ms.

>gcc32-avx2
734 ms.
1116 ms.
1676 ms.

>msvc32-sse
2713 ms.
3982 ms.
298870 ms.

>msvc32-avx
2741 ms.
3605 ms.
295643 ms.

>msvc32-avx2
2747 ms.
3606 ms.
295639 ms.

Не, я конечно и делал этот тест для демонстрации преимущества gcc, но разница более чем в 100 раз показалась всё же каким-то перебором. Тем более, что мой собеседник демонстрировал совсем других цифры. Тут была явно какая-то ошибка. Но я не мог подумать на компилятор и начал искать у себя — перебирал разные опции компилятора, варианты подключения библиотек и т.п. Но ничего не помогало. Я уже даже начал думать о магическом влияние Qt и т.п. невероятных вещах, когда мне в голову пришла совершенно наркоманская мысль: у моего собеседника в теле цикла было уведомление GUI о прогрессе прохождения теста (которое я естественно выкинул при переписывание) — поставлю ка и я нечто подобное (закомментированная строка в коде выше, причём самое забавное, что cout там никогда не выполняется). И что вы думаете? Оно заработало нормально:
  результат2
>gcc32-sse
1425 ms.
1984 ms.
3007 ms.

>gcc32-avx
1421 ms.
1116 ms.
1676 ms.

>gcc32-avx2
734 ms.
1116 ms.
1675 ms.

>msvc32-sse
1378 ms.
2039 ms.
3985 ms.

>msvc32-avx
1370 ms.
1434 ms.
3974 ms.

>msvc32-avx2
807 ms.
1399 ms.
1887 ms.

Эти результаты меня уже ничем не удивили — всё как я и предполагал, 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
Автор: alex_public
Дата: 12.03.17
.

Так же судя по сообщениям коллег с форума можно локализовать данную проблему по версиям MSVC: подвержены версии VS 2013, 2015, 2017. И для 32-ух и для 64-ёх битного кода.
Отредактировано 13.03.2017 15:20 alex_public . Предыдущая версия . Еще …
Отредактировано 13.03.2017 10:34 alex_public . Предыдущая версия .
Отредактировано 11.03.2017 8:45 alex_public . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.