Сегодня с удивлением заметил проблему: колоссальное падение производительности при попытке вычислить максимальное значение. Код вот такой:
C++ Source Code:
float f = somestuff;
f = max( f, 0 );
max стандартно определён как макрос в minmax.h:
C++ Source Code:
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#endif
Так вот этот код, будучи скомпилирован в MSVC2010, выполняется в три (!) раза медленнее, чем в MinGW!
Смотрим ассемблер:
code: fld DWORD PTR _dp$68919[ebp]
fcom ST(1)
fnstsw ax
test ah, 65 ; 00000041H
jne SHORT $LN26@Mathlib_In@6
fstp DWORD PTR tv194[ebp]
jmp SHORT $LN21@Mathlib_In@6
$LN26@Mathlib_In@6:
fstp ST(0)
fst DWORD PTR tv194[ebp]
$LN21@Mathlib_In@6:
fld DWORD PTR tv194[ebp]
Вот что это за дерьмецо, товарищи? Какого чёрта он лезет за нулём в стек? Проверяет контрольное слово, вынося его в ax? Джампы какие-то? И ладно бы, в дебаге. Это В РЕЛИЗЕ, при максимальной оптимизации!
А вот что генерит MinGW:
Красивый и быстрый код. Ноль берём из fldz, выбор значения делаем специально сделанной для этого кондишнл-инструкцией fcmovb.
Ну, собсно, два вопроса:
1) Почему компилятор MSVC2010 - говно наипреговённейшее, говнявое, преговённое, которое без предупреждения генерит в релизе такой жутко неоптимальный код?
2) Как обойти эту проблему? Я и темплейт-функциями пытался, и опции компилятора всякие крутил. Нифига. Вот стабильно такой код. Ощущение, будто в Microsoft не знают половину инструкций сопроцессора. Но это же бред, верно? Но зато теперь понятно, почему волатила так тормозит.
А может быть, это только мой компилятор взбесился? У других всё нормально?
Skaarj раз этот код такой, то и весь остальной такой же. Не на ассемблере же теперь писать. Проще компилировать через minGW, но это может не вариант.
Попробую посмотреть позже как на vs2013.
Можно полный пример кода? Чтобы функцию оптимизацией не откинуло.
Skaarj писал: А если заменить ассемблерной вставкой и забыть про это?
Не получится. Этот код полагается на содержимое стека сопроцессора. Если выносить в отдельную функцию - потребуются дополнительные fld/fsp, и теряются возможности по оптимизации типа instruction flow.
Это во-первых. А во-вторых, в 64-битном коде всё компилируется с использованием SSE-инструкций (неоптимально, конечно, но тем не менее), и FPU-код там будет не в тему.
XaeroX
Да. 2013 студия с тулсетом от visual studio 2010 express.
Как я понял с этой express нельзя на x64 компилировать. По крайней мере, мне написало, что тулсет не установлен.
Хорошо хоть community edition теперь сделали, где, вроде, ничего не урезано и можно vs assist поставить.
Меня 2010 студия во всём устраивала. До вчерашнего дня, пока не обнаружился этот досадный баг. Который, по всей видимости, частично и в 2013 остался - раз код по-прежнему недостаточно оптимален.
Переходить на MinGW не вариант, там своих проблем хватает. В целом микрософтовский компилятор мне показался надёжнее. Но вот как это говно забороть-то?
XaeroX
Могу попробовать ещё на vs 2015. Для сравнения, так сказать. Исправились ли они или ошибки тащат в следующие релизы.
И в саппорт, наверное, им надо репортнуть. Может что скажут.
ComradeAndrew писал: Могу попробовать ещё на vs 2015.
Попробуй, пожалуйста.
Но, возможно, они уже забили на тулсет 100.
Цитата:
ComradeAndrew писал: Может что скажут.
А то я не знаю, что они скажут. Скажут "купите виндовс 10 и вижуал студию 2015, а тулсет 100 - легаси и депрекейтед".
А то, что вы хотите поддерживать процессоры без SSE - это ваши глубоко личные проблемы.
ComradeAndrew
Опять ты SSE-код показываешь. Да знаю я, знаю, что под SSE нормально всё. В 2010 тоже нормально под х64. Меня интересует исключительно FPU-код, совместимый.