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