Неприятное открытие
От: кт  
Дата: 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-разряда оставлен для совместимости. А вот по этому тесту выходит наоборот
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.