Неприятное открытие
От: кт  
Дата: 23.04.17 07:38
Оценка:
Похвастался коллеге, что мы в ногу с прогрессом используем 64-разрядный транслятор, а он, небось, по старинке – 32-разрядный.
Ну и он попросил дать ему 64-разрядный компилятор. Задачи у него почти чисто вычислительные. Главный процесс – численное интегрирование. Поэтому производительность важна – чем быстрее считается, тем меньше шаг интегрирования можно задать.
Попробовал. Говорит, перетранслировал – коды стали больше (ну, это ожидаемо). А скорость стала ниже!
Я сначала не поверил. Забрал его тексты проверил. И вот, что получилось.
Процессор Intel Core i5-3210M 2.5 GHz. Стоит Windows-7.
Одна и та же задача. Результаты выдает одинаковые. Компилятор (не скажу с какого языка  ) 64-разряда сделан из 32-х разрядного, поэтому команды очень похожие.
Размер кода увеличился на 9%, а скорость упала на 20.5%. Расчет длинный, ввода-вывода мало.
Попробовал разобраться.
Ну да, там, где индексы, их надо бы перевести в 8 байт, но не хочется трогать исходные тексты. Поэтому для 64 разрядов появляется лишняя пересылка, которая вероятно не дает свернуть адресацию в SIB-байт.
Вот одно и то же место:
A12(i,j)=0.0;       64 разряда
0013CD 48630580000000     movsxq rax,I
0013D4 486BF818           imul q rdi,rax,24
0013D8 48630584000000     movsxq rax,J
0013DF 48C1E003           shl  q rax,3
0013E3 4803F8             add  q rdi,rax
0013E6 488DBFE0FFFFFF     lea    rdi,@A12+0FFFFFFE0h[rdi]
0013ED BE28010000         mov  q rsi,offset @00000128h
0013F2 48A5               movsq

A12(i,j)=0.0;    32 разряда
001393 6B3D8000000018     imul   edi,I,24
00139A A184000000         mov    eax,J
00139F 8DBCC7E0FFFFFF     lea    edi,@A12+0FFFFFFE0h[edi+eax*8]
0013A6 BE28010000         mov    esi,offset @00000128h
0013AB A5                 movs
0013AC A5                 movs

Но это все нечасто встречающийся код. Большая часть состоит из вот таких операторов:
32 разряда:
A02(3,3)=-SPH2*STH2*SPS2+CPH2*CPS2;
001334 BB70020000         mov    ebx,offset SPH2
001339 DD03               fld64  [ebx]
00133B 53                 push   ebx
00133C 53                 push   ebx
00133D D9E0               fchs
00133F BB50020000         mov    ebx,offset STH2
001344 DC0B               fmul64 [ebx]
001346 BB30020000         mov    ebx,offset SPS2
00134B DC0B               fmul64[ebx]
00134D DD1C24             fst64p[esp]
001350 BB28020000         mov    ebx,offset CPS2
001355 BA68020000         mov    edx,offset CPH2
00135A E800000000         call   ?FMS_M
00135F DD1D40000000       fst64p @A02+000000040h

64 разряда
A02(3,3)=-SPH2*STH2*SPS2+CPH2*CPS2;
00136F BB78020000         mov  q rbx,offset SPH2
001374 DD03               fld64[rbx]
001377 53                 push rbx
001378 D9E0               fchs
001379 BB58020000         mov  q rbx,offset STH2
00137E DC0B               fmul64[rbx]
001380 BB38020000         mov  q rbx,offset SPS2
001385 DC0B               fmul64[rbx]
001387 DD1C24             fst64p[rsp]
00138A BB30020000         mov  q rbx,offset CPS2
00138F BA70020000         mov  q rdx,offset CPH2
001394 E800000000         call   ?FMS_M
001399 DD1D40000000       fst64p @A02+000000040h

Практически одни и те же команды и это 95% всего выполняемого расчета. Компилятор даже константы загружает без префикса 48 потому, что код не превышает 4 Гбайт.

Итак, имеем две почти одинаковых последовательности команд в двух режимах, проводящих одни и те же вычисления, главным образом, через FPU.
Исходные тексты одинаковы. Код в 64 разряда ожидаемо увеличивается.
А скорость его работы падает на 20%!

Я читал (и считал), что теперь 64-разряда – это «родной» режим, а 32-разряда оставлен для совместимости. А вот по этому тесту выходит наоборот
Re: Неприятное открытие
От: Stanislaw K СССР  
Дата: 23.04.17 08:26
Оценка:
Здравствуйте, кт, Вы писали:

кт>Попробовал. Говорит, перетранслировал – коды стали больше (ну, это ожидаемо). А скорость стала ниже!

кт>Я сначала не поверил. Забрал его тексты проверил. И вот, что получилось.
кт>Процессор Intel Core i5-3210M 2.5 GHz. Стоит Windows-7.

кт>Я читал (и считал), что теперь 64-разряда – это «родной» режим, а 32-разряда оставлен для совместимости. А вот по этому тесту выходит наоборот


Это смотря с какого момента "теперь".

Processor Number i5-3210M
Status Launched
Launch Date Q2'12


http://ark.intel.com/products/67355/Intel-Core-i5-3210M-Processor-3M-Cache-up-to-3_10-GHz-rPGA
Все проблемы от жадности и глупости
Re: Неприятное открытие
От: denisko http://sdeniskos.blogspot.com/
Дата: 23.04.17 08:57
Оценка: +2
Здравствуйте, кт, Вы писали:

Очень странно выглядит если честно. Во-первых, если это оптимизрованный код какого хрена он используется FPU вместо AVX/SSE. Второе, какого хрена он все время в память лезет аргументы загружать. __restrict/__declspec ( restrict нигде не забыл?
<Подпись удалена модератором>
Скорость в 64 битах (Re: Неприятное открытие)
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 08:59
Оценка: 1 (1) +1
Здравствуйте, кт, Вы писали:

кт>Ну да, там, где индексы, их надо бы перевести в 8 байт, но не хочется трогать исходные тексты. Поэтому для 64 разрядов появляется лишняя пересылка, которая вероятно не дает свернуть адресацию в SIB-байт.

кт>Вот одно и то же место:
кт>
кт>A12(i,j)=0.0;       64 разряда
кт>0013CD 48630580000000     movsxq rax,I
кт>0013D4 486BF818           imul q rdi,rax,24
кт>0013D8 48630584000000     movsxq rax,J
кт>0013DF 48C1E003           shl  q rax,3
кт>0013E3 4803F8             add  q rdi,rax
кт>0013E6 488DBFE0FFFFFF     lea    rdi,@A12+0FFFFFFE0h[rdi]
кт>0013ED BE28010000         mov  q rsi,offset @00000128h
кт>0013F2 48A5               movsq

кт>A12(i,j)=0.0;    32 разряда
кт>001393 6B3D8000000018     imul   edi,I,24
кт>00139A A184000000         mov    eax,J
кт>00139F 8DBCC7E0FFFFFF     lea    edi,@A12+0FFFFFFE0h[edi+eax*8]
кт>0013A6 BE28010000         mov    esi,offset @00000128h
кт>0013AB A5                 movs
кт>0013AC A5                 movs
кт>


Хм. Попробую смоделировать у себя. Раз I умножается на 24, а J на 8, значит, размер по I равен 3? Я не буду для C моделировать адресацию массива от 1:

double f01(double A12[][3], int i, int j) {
        return A12[i][j];
}


Результат (тут и далее — x86-64, GCC 5.4.0, AT&T ассемблер; SysV конвенция — аргументы поступают: rdi, rsi, rdx, rcx...):
f01:
.LFB0:
        .cfi_startproc
        movslq  %esi, %rsi
        leaq    (%rsi,%rsi,2), %rax
        leaq    (%rdi,%rax,8), %rax
        movslq  %edx, %rdx
        movsd   (%rax,%rdx,8), %xmm0
        ret


Хорошо видно, что отличается: ваш пример совсем не использует адресацию от двух регистров (базового плюс индексного). Ну и IMUL на 24 разложен в два LEA (не столь существенно). У вас же в примере какой-то кошмарик.

Ну хорошо, возьмём от того же GCC5 — gfortran:

      function f02(a12, i, j)
      double precision f02
      double precision a12(3,3)
      integer i, j
      f02 = a12(i, j)
      end


Результат:

f02_:
.LFB0:
        .cfi_startproc
        movslq  (%rdx), %rax
        movslq  (%rsi), %rdx
        leaq    (%rax,%rax,2), %rax
        leaq    -4(%rdx,%rax), %rax
        movsd        (%rdi,%rax,8), %xmm0
        ret


Первые два movslq — взятие значения аргумента по ссылке, дальше — код взятия по индексу.

Вывод: с процессором, скорее всего, всё в порядке. А вот компилятор для 64-битного режима у вас, мягко говоря, фиговый.
Назовёте марку и версию компилятора?

кт>64 разряда

кт>
кт>A02(3,3)=-SPH2*STH2*SPS2+CPH2*CPS2;
кт>00136F BB78020000         mov  q rbx,offset SPH2
кт>001374 DD03               fld64[rbx]
кт>001377 53                 push rbx
кт>001378 D9E0               fchs
кт>001379 BB58020000         mov  q rbx,offset STH2
кт>00137E DC0B               fmul64[rbx]
кт>001380 BB38020000         mov  q rbx,offset SPS2
кт>001385 DC0B               fmul64[rbx]
кт>001387 DD1C24             fst64p[rsp]
кт>00138A BB30020000         mov  q rbx,offset CPS2
кт>00138F BA70020000         mov  q rdx,offset CPH2
кт>001394 E800000000         call   ?FMS_M
кт>001399 DD1D40000000       fst64p @A02+000000040h
кт>

кт>Практически одни и те же команды и это 95% всего выполняемого расчета. Компилятор даже константы загружает без префикса 48 потому, что код не превышает 4 Гбайт.

Интересно, кто и зачем использует FPU в 64-битном режиме. MS категорически переключилась на SSE для 64-битки. Unix переключаются по умолчанию, но могут включать FPU для усиленного распараллеливания. Повторяю вопрос про компилятор.

кт>Итак, имеем две почти одинаковых последовательности команд в двух режимах, проводящих одни и те же вычисления, главным образом, через FPU.

кт>Исходные тексты одинаковы. Код в 64 разряда ожидаемо увеличивается.
кт>А скорость его работы падает на 20%!

Специфика Intel? Есть AMD для сравнения? Тот более лояльно относится к FPU в 64-битке.

кт>Я читал (и считал), что теперь 64-разряда – это «родной» режим, а 32-разряда оставлен для совместимости. А вот по этому тесту выходит наоборот


Вообще-то для раннего Intel это было, по слухам, вполне верно — они настолько быстро и грязно сделали EM64T, что в первых его версиях (для Pentium 4) 64-битный код вообще не имел никакого out-of-order. Но уже начиная с Core, AFAIK, это не так. И ваш i7 должен вполне нормально это отрабатывать.

И кто такой FMS_M? Это проверка границ массива? А если её отключить, что получится со скоростью?

А почему одни и те же регистры (rbx, rdx) по кругу? Или это только в одном таком куске кода? Я понимаю, что переименование регистров спасает отцов русской демократии в 95% случаев, но компилятор явно без SSA, а постоянные дёргания регистров через стек дороги в любом варианте. А с учётом FPU, непонятно, что это за диковинка такая.

Возьмите GNU Fortran, возьмите интеловский, и сравните. Я подозреваю, что картина выровняется, а, может, 64-битка станет и быстрее (за счёт прямого использования большего количества регистров).
The God is real, unless declared integer.
Отредактировано 23.04.2017 9:01 netch80 . Предыдущая версия . Еще …
Отредактировано 23.04.2017 9:00 netch80 (заголовок) . Предыдущая версия .
Re: Неприятное открытие
От: кт  
Дата: 23.04.17 09:13
Оценка:
так и знал, что все найдут генерируемый код плохим.

А речь о том, что почти ОДИНАКОВЫЕ последовательности команд в 64-разрядном режиме работают на 20% медленнее, чем в они же 32 разрядном режиме.
Хотя по идее должны были бы работать ТАКЖЕ (плохо или хорошо, это уже второй вопрос)

И, кстати, SSE это не совсем то же, что FPU. В FPU реально работа идет с 80 разрядами, поэтому очень хорошее округление и точность. Промежуточные результаты можно запомнить командой FST80. А в SSE2-4 чем?
Все эти 128 и 256 разрядные регистры все (по времени) теряют на загрузках. Тоже, увы, проверено.
Re: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 09:22
Оценка:
Здравствуйте, кт, Вы писали:

И второе вдогонку — буду приводить по-прежнему примеры для Фортрана — попытался сэмулировать вторую часть с присвоением одного результата умножения.

Входной код

      function f03(a02)
      common /globals/ SPH2, STH2, SPS2, CPH2, CPS2
      double precision f03
      double precision a02(3,3)
      A02(3,3)=-SPH2*STH2*SPS2+CPH2*CPS2
      end


Сгенерированное с принуждением к FPU:

f03_:
        flds    globals_+12(%rip)
        fmuls   globals_+16(%rip)
        flds    globals_(%rip)
        fmuls   globals_+4(%rip)
        fmuls   globals_+8(%rip)
        fsubrp  %st, %st(1)
        fstpl   64(%rdi)
        ret


Или в дизассемблере:

0000000000000000 <f03_>:
   0:   d9 05 00 00 00 00       flds   0x0(%rip)        # 6 <f03_+0x6>
   6:   d8 0d 00 00 00 00       fmuls  0x0(%rip)        # c <f03_+0xc>
   c:   d9 05 00 00 00 00       flds   0x0(%rip)        # 12 <f03_+0x12>
  12:   d8 0d 00 00 00 00       fmuls  0x0(%rip)        # 18 <f03_+0x18>
  18:   d8 0d 00 00 00 00       fmuls  0x0(%rip)        # 1e <f03_+0x1e>
  1e:   de e9                   fsubrp %st,%st(1)
  20:   dd 5f 40                fstpl  0x40(%rdi)
  23:   c3                      retq

(0 в смещениях — потому что отдельный объектник. В готовом бинарнике будут реальные цифры.)

Сравниваем с тем, что у вас:

кт>
кт>A02(3,3)=-SPH2*STH2*SPS2+CPH2*CPS2;
кт>00136F BB78020000         mov  q rbx,offset SPH2
кт>001374 DD03               fld64[rbx]
кт>001377 53                 push rbx
кт>001378 D9E0               fchs
кт>001379 BB58020000         mov  q rbx,offset STH2
кт>00137E DC0B               fmul64[rbx]
кт>001380 BB38020000         mov  q rbx,offset SPS2
кт>001385 DC0B               fmul64[rbx]
кт>001387 DD1C24             fst64p[rsp]
кт>00138A BB30020000         mov  q rbx,offset CPS2
кт>00138F BA70020000         mov  q rdx,offset CPH2
кт>001394 E800000000         call   ?FMS_M
кт>001399 DD1D40000000       fst64p @A02+000000040h
кт>


Учитывая, что "mov q rbx,offset SPH2" грузит 4 байта, и адресация по RIP тоже с 4-байтными смещениями, реально имеем такое же ограничение на помещение статических данных в 2GB (с учётом знаковости). Выше этой границы допускается только динамически распределяемая память. Тогда
1) компилятор совсем не умеет использовать адресацию по RIP;
2) как минимум, команды FSUBR[P] он не знает.

[UPD: deleted — не досмотрел, что часть операндов берётся из памяти]
The God is real, unless declared integer.
Отредактировано 23.04.2017 12:02 netch80 . Предыдущая версия .
Re[2]: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 09:28
Оценка:
Здравствуйте, кт, Вы писали:

кт>так и знал, что все найдут генерируемый код плохим.


Да, и это правильно. Потому что пример с загрузкой константы очевидно хуже написан в 64 битах, чем в 32. Сами же сказали, что в 64 битах компилятор чего-то не сумел. А я показываю, что это проблема не режима, а компилятора, что он очевидно слаб.

кт>А речь о том, что почти ОДИНАКОВЫЕ последовательности команд в 64-разрядном режиме работают на 20% медленнее, чем в они же 32 разрядном режиме.


Вы это можете доказать, только избавившись от посторонних влияний типа FMS_M. Неизвестно их качество.
Или проанализируйте чем-то вроде Intel VTune, который умеет (AFAIR) показывать тормоза вплоть до конкретной машинной команды и исходной строчки. Или — повторюсь — проверьте с AMD.

кт>Хотя по идее должны были бы работать ТАКЖЕ (плохо или хорошо, это уже второй вопрос)


По форме: "так же" пишется в данном случае раздельно.

кт>И, кстати, SSE это не совсем то же, что FPU. В FPU реально работа идет с 80 разрядами, поэтому очень хорошее округление и точность. Промежуточные результаты можно запомнить командой FST80. А в SSE2-4 чем?


В FPU "реально" работа идёт с точностью согласно режиму процессора. Вы точно выставили extended? Или хотя бы проверили, что оно такое? В винде в 32 битах по умолчанию там double, так же, как и во FreeBSD (а вот в Linux — extended).

Аргумент, что в FPU можно считать в 80 битах, принимаю. Иногда это даже полезно. Но обычно эту пользу переоценивают.

кт>Все эти 128 и 256 разрядные регистры все (по времени) теряют на загрузках. Тоже, увы, проверено.


Какие именно загрузки? Там несколько разных.
The God is real, unless declared integer.
Re[3]: Неприятное открытие
От: кт  
Дата: 23.04.17 09:50
Оценка:
Здравствуйте, netch80, Вы писали:

N>Да, и это правильно. Потому что пример с загрузкой константы очевидно хуже написан в 64 битах, чем в 32. Сами же сказали, что в 64 битах компилятор чего-то не сумел. А я показываю, что это проблема не режима, а компилятора, что он очевидно слаб.


Ухудшение кода есть, но оно никак не может дать 20% замедление, поскольку в основных циклах встречается очень редко.

N>Вы это можете доказать, только избавившись от посторонних влияний типа FMS_M. Неизвестно их качество.

внутри этой системной подпрограммки команды тоже одинаковые для 32 и 64

N>Или проанализируйте чем-то вроде Intel VTune, который умеет (AFAIR) показывать тормоза вплоть до конкретной машинной команды и исходной строчки. Или — повторюсь — проверьте с AMD.

На AMD обязательно проверю

кт>>Хотя по идее должны были бы работать ТАКЖЕ (плохо или хорошо, это уже второй вопрос)


N>По форме: "так же" пишется в данном случае раздельно.

Спасибо, постараюсь проверять написанное более тщательно

N>В FPU "реально" работа идёт с точностью согласно режиму процессора. Вы точно выставили extended? Или хотя бы проверили, что оно такое? В винде в 32 битах по умолчанию там double, так же, как и во FreeBSD (а вот в Linux — extended).

Внутри FPU все идет в 80 разрядах. "Реально" — я имел ввиду "внутри"

N>Аргумент, что в FPU можно считать в 80 битах, принимаю. Иногда это даже полезно. Но обычно эту пользу переоценивают.

А ошибки IEEE-754 обычно недооценивают.

кт>>Все эти 128 и 256 разрядные регистры все (по времени) теряют на загрузках. Тоже, увы, проверено.


N>Какие именно загрузки? Там несколько разных.

Я уже выкладывал этот плач Ярославны
https://groups.google.com/forum/#!topic/comp.lang.asm.x86/j7wBKVUOmfI

И все-таки еще раз: одинаковые команды в двух режимах и должны были бы выполняться одинаково быстро (медленно)
Re[2]: Неприятное открытие
От: кт  
Дата: 23.04.17 10:33
Оценка:
Здравствуйте, netch80, Вы писали:

N>Учитывая, что "mov q rbx,offset SPH2" грузит 4 байта, и адресация по RIP тоже с 4-байтными смещениями, реально имеем такое же ограничение на помещение статических данных в 2GB (с учётом знаковости). Выше этой границы допускается только динамически распределяемая память. Тогда

И это действительно так, в таких программах (о, ужас) команды и статические данные не могут превысить 4 Гбайт.
Кстати, реальный размер исследуемой программы 500 Кбайт кодов.

N>1) компилятор совсем не умеет использовать адресацию по RIP;

Здесь она ничего не дает в плане объема/скорости, статические данные не "рассыпаны" между кодов.
N>2) как минимум, команды FSUBR[P] он не знает.
А в чем будет выигрыш? Кстати, подпрограмма FMS_M, судя по всему, выполняет сразу и умножение и сложение.

N>И ещё одно (которое уже по счёту) — смысла писать fmul64 нет! fmul одинаков для всех, а точность задаётся режимом процессора. (В отличие от load/store, которое таки имеет размер операнда в памяти.) Это не имеет отношения к скорости, но имеет отношение к интеллекту авторов компилятора.


А вот сейчас стало обидно за авторов, да.
значит, писать безликие flds 0x0(%rip) это интеллект,
а явно и наглядно указывать fld64 [rbx] вместо какого-нибудь громоздкого fld q ptr [rbx] это плохо.
Re[4]: Неприятное открытие
От: Michael7 Россия  
Дата: 23.04.17 11:05
Оценка:
Здравствуйте, кт, Вы писали:

кт>И все-таки еще раз: одинаковые команды в двух режимах и должны были бы выполняться одинаково быстро (медленно)


А этого, по-моему, никогда не было на x86. 8-битные команды (с AH,AL, короткими переходами и прочим) выполнялись быстрее 16-ти битных, а 16-ти битные были быстрее 32-битных. Между прочим, попробуйте ради любопытства запустить аналогичный 16-ти битный код в MS-DOS, не исключено, что код и сейчас будет быстрее 32-битного. Хотя сейчас вспомнил, что вроде как раз начиная с P6 (i686, Pentium Pro и Pentium-II) оптимизатор исполнения в процессоре стал плохо работать с 16-ти битным кодом, так что возможно сейчас он уже сильно устарел и выигрыша не будет. Но он был вплоть до первых пентиумов включительно.
Отредактировано 23.04.2017 11:08 Michael7 . Предыдущая версия .
Re[3]: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 11:05
Оценка:
Здравствуйте, кт, Вы писали:

N>>2) как минимум, команды FSUBR[P] он не знает.

кт>А в чем будет выигрыш?

Чуть меньше возни.

кт> Кстати, подпрограмма FMS_M, судя по всему, выполняет сразу и умножение и сложение.


А, это fused multiply and subtract? Понятно. Вряд ли оно выполняет fused с ещё более расширенной точностью, так что вынесение в подпрограмму явно не имеет смысла, но сравнение скорости оно, таки да, не портит.

N>>И ещё одно (которое уже по счёту) — смысла писать fmul64 нет! fmul одинаков для всех, а точность задаётся режимом процессора. (В отличие от load/store, которое таки имеет размер операнда в памяти.) Это не имеет отношения к скорости, но имеет отношение к интеллекту авторов компилятора.


кт>А вот сейчас стало обидно за авторов, да.


Потому что криво читаете.

кт>значит, писать безликие flds 0x0(%rip) это интеллект,

кт>а явно и наглядно указывать fld64 [rbx] вместо какого-нибудь громоздкого fld q ptr [rbx] это плохо.

fld64 — это то же, что fldl в AT&T (fld32 == flds, fld80 == fldt). Тут разницы нет, кроме стиля. Команды разные.

Я говорю про _арифметику_. fmul32, fmul64, fmul80 пишутся одним и тем же кодом, и точность будет выбираться согласно режиму FPU, а не тем, какую точность записали в ассемблере. Поэтому ставить точность после fmul не просто бессмысленно, а и вредно для читающего.
The God is real, unless declared integer.
Re[4]: Неприятное открытие
От: Michael7 Россия  
Дата: 23.04.17 11:15
Оценка:
Здравствуйте, netch80, Вы писали:

N>Я говорю про _арифметику_. fmul32, fmul64, fmul80 пишутся одним и тем же кодом, и точность будет выбираться согласно режиму FPU, а не тем, какую точность записали в ассемблере. Поэтому ставить точность после fmul не просто бессмысленно, а и вредно для читающего.


Может быть указание точности приводит к генерации кода, устанавливающего нужный режим работы FPU (FLDCW)?
Re[4]: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 11:22
Оценка:
Здравствуйте, кт, Вы писали:

N>>Да, и это правильно. Потому что пример с загрузкой константы очевидно хуже написан в 64 битах, чем в 32. Сами же сказали, что в 64 битах компилятор чего-то не сумел. А я показываю, что это проблема не режима, а компилятора, что он очевидно слаб.

кт>Ухудшение кода есть, но оно никак не может дать 20% замедление, поскольку в основных циклах встречается очень редко.

Ну тогда — не знаю аналога для Windows, но тут я бы напустил на неё perf stat и померял, где основные тормоза (фронтэнд, бэкэнд, кэш, ветвления...)

N>>В FPU "реально" работа идёт с точностью согласно режиму процессора. Вы точно выставили extended? Или хотя бы проверили, что оно такое? В винде в 32 битах по умолчанию там double, так же, как и во FreeBSD (а вот в Linux — extended).

кт>Внутри FPU все идет в 80 разрядах. "Реально" — я имел ввиду "внутри"

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

N>>Аргумент, что в FPU можно считать в 80 битах, принимаю. Иногда это даже полезно. Но обычно эту пользу переоценивают.

кт>А ошибки IEEE-754 обычно недооценивают.

Какие именно ошибки? Погрешности принципа плавучки, ошибки реализации, другое?
В любом случае, как только вы выгружаете из FPU в double, а не long double, точность усекается. И ваш код всё время содержит именно такие усечения (fstp64 и тому подобное).

кт>>>Все эти 128 и 256 разрядные регистры все (по времени) теряют на загрузках. Тоже, увы, проверено.


N>>Какие именно загрузки? Там несколько разных.

кт>Я уже выкладывал этот плач Ярославны
кт>https://groups.google.com/forum/#!topic/comp.lang.asm.x86/j7wBKVUOmfI

Мнэээ... я правильно понял, что вся проблема была в использовании AVX после SSE без vzeroupper? Тогда — удивляюсь, потому что это уровень букваря. Но даже это даёт только начальный тормоз работы с одним конкретным регистром.

кт>И все-таки еще раз: одинаковые команды в двух режимах и должны были бы выполняться одинаково быстро (медленно)


Давайте пока не спешить с выводами. У вас есть возможность прогнать через аппаратные счётчики? i5-3210M это Ivy Bridge, у него этих счётчиков уже есть на все случаи жизни.
The God is real, unless declared integer.
Re[5]: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 11:24
Оценка:
Здравствуйте, Michael7, Вы писали:

N>>Я говорю про _арифметику_. fmul32, fmul64, fmul80 пишутся одним и тем же кодом, и точность будет выбираться согласно режиму FPU, а не тем, какую точность записали в ассемблере. Поэтому ставить точность после fmul не просто бессмысленно, а и вредно для читающего.

M>Может быть указание точности приводит к генерации кода, устанавливающего нужный режим работы FPU (FLDCW)?

Эээ... это замедлило бы раз в 10 по сравнению с конкурентами. Честно, даже для компилятора с такими тараканами это чересчур.
The God is real, unless declared integer.
Re[4]: Неприятное открытие
От: Michael7 Россия  
Дата: 23.04.17 11:25
Оценка:
Здравствуйте, кт, Вы писали:

кт>Я уже выкладывал этот плач Ярославны

кт>https://groups.google.com/forum/#!topic/comp.lang.asm.x86/j7wBKVUOmfI

Кстати, вас вероятно заинтересует статья "Как я сделал самый быстрый ресайз изображений. Часть 2, SIMD" https://habrahabr.ru/post/326900/ Ее автор описывает как он добился двух-трех кратного ускорения путем использования инструкций SSE2-SSE4. Что интересно, использование AVX такого большого прироста не дало, а в ряде случаев привело даже к падению производительности. Но не из-за проблем с AVX, а из-за того, что процессор Intel Core i5-4258U — ноутбучный (у вас вроде тоже) и он сбрасывает частоту при полной загрузке AVX. Причем это не тротлинг, температура так сильно не вырастала. На процессорах Xeon такого эффекта нет и там использование AVX не приводило к падению производительности.
Re[5]: Неприятное открытие
От: кт  
Дата: 23.04.17 11:29
Оценка:
Здравствуйте, Michael7, Вы писали:

M>Кстати, вас вероятно заинтересует статья "Как я сделал самый быстрый ресайз изображений. Часть 2, SIMD" https://habrahabr.ru/post/326900/ Ее автор описывает как он добился двух-трех кратного ускорения путем использования инструкций SSE2-SSE4. Что интересно, использование AVX такого большого прироста не дало, а в ряде случаев привело даже к падению производительности. Но не из-за проблем с AVX, а из-за того, что процессор Intel Core i5-4258U — ноутбучный (у вас вроде тоже) и он сбрасывает частоту при полной загрузке AVX. Причем это не тротлинг, температура так сильно не вырастала. На процессорах Xeon такого эффекта нет и там использование AVX не приводило к падению производительности.


Спасибо, обязательно учту и проверю
Re[6]: Неприятное открытие
От: Michael7 Россия  
Дата: 23.04.17 11:30
Оценка:
Здравствуйте, netch80, Вы писали:

M>>Может быть указание точности приводит к генерации кода, устанавливающего нужный режим работы FPU (FLDCW)?


N>Эээ... это замедлило бы раз в 10 по сравнению с конкурентами. Честно, даже для компилятора с такими тараканами это чересчур.


Если это делать перед каждой командой, то конечно замедлило бы и как бы не более, чем в 10. Но если один раз перед первым употреблением, а потом отслеживать изменились требования к точности или нет, то лишнего кода не будет. Я это к тому, что в принципе в указании точности некий смысл есть, хотя далеко не факт, что в обсуждаемом компиляторе так сделано.
Re[6]: Неприятное открытие
От: кт  
Дата: 23.04.17 11:37
Оценка:
Здравствуйте, netch80, Вы писали:

N>>>Я говорю про _арифметику_. fmul32, fmul64, fmul80 пишутся одним и тем же кодом, и точность будет выбираться согласно режиму FPU, а не тем, какую точность записали в ассемблере. Поэтому ставить точность после fmul не просто бессмысленно, а и вредно для читающего.

M>>Может быть указание точности приводит к генерации кода, устанавливающего нужный режим работы FPU (FLDCW)?

N>Эээ... это замедлило бы раз в 10 по сравнению с конкурентами. Честно, даже для компилятора с такими тараканами это чересчур.


честно, говоря, я вообще не понимаю, о чем речь. Вот команды загрузки
DD03                fld64 [rbx]     операнд в памяти 8 байт
D903                fld32 [rbx]     операнд в памяти 4 байта
D9C0                fld st          операнд в стеке 10 байт


Причем здесь "точность ассемблера" ? Размер операнда определяет бит в коде операции, что и показывает "неинтеллектуальный" дисассемблер
Re[7]: Неприятное открытие
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 11:40
Оценка:
Здравствуйте, кт, Вы писали:

N>>>>Я говорю про _арифметику_. fmul32, fmul64, fmul80 пишутся одним и тем же кодом, и точность будет выбираться согласно режиму FPU, а не тем, какую точность записали в ассемблере. Поэтому ставить точность после fmul не просто бессмысленно, а и вредно для читающего.

M>>>Может быть указание точности приводит к генерации кода, устанавливающего нужный режим работы FPU (FLDCW)?
N>>Эээ... это замедлило бы раз в 10 по сравнению с конкурентами. Честно, даже для компилятора с такими тараканами это чересчур.

кт>честно, говоря, я вообще не понимаю, о чем речь. Вот команды загрузки

кт>
кт>DD03                fld64 [rbx]     операнд в памяти 8 байт
кт>D903                fld32 [rbx]     операнд в памяти 4 байта
кт>D9C0                fld st          операнд в стеке 10 байт
кт>


кт>Причем здесь "точность ассемблера" ? Размер операнда определяет бит в коде операции, что и показывает "неинтеллектуальный" дисассемблер


В третий раз повторяю: fmul, а не fld! Повторите для него и убедитесь.
The God is real, unless declared integer.
Re[8]: Неприятное открытие
От: кт  
Дата: 23.04.17 11:50
Оценка:
Здравствуйте, netch80, Вы писали:

N>В третий раз повторяю: fmul, а не fld! Повторите для него и убедитесь.

повторил
 DC0B                fmul64 [rbx]  операнд в памяти 8 байт
 D80B                fmul32 [rbx]  операнд в памяти 4 байта
 DCCA                fmul st2,st0  операнды в стеке 10 байт
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.