Форум: "Прочее";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];
ВнизАссемблер в Delphi Найти похожие ветки
← →
Evgheni86 (2006-08-27 14:12) [0]Доброго времени суток!
Слегка изучив ассемблер я попытался создать быстрый код
для вычисления известного фрактала Множество Мандельброта
Мне показалось, что Deplhi не очень оптимизирвано(по скорости)
использует FPU и работает с Real числами Например
Объявлены две Real переменные a и b(локалки)
Если мы напишем a:=b, то в диззассемблере
это будет выглядеть так:
mov eax, [ebp+$10]
mov [ebp+$08], eax
mov eax, [ebp+$0C]
mov [ebp+$04], eax
то есть простое копирование осуществляется в четыре этапа!
А можго написать:
asm
fld a
fstp b
end;
В моём случае это дало ускорение на 30%!
Я решил не останавливаться на дастигнутом и переписал всю процедуру
на ассемблер. В основном я старался избежать частых обращений к памяти,
и для хранения локальных переменных и констант использовал FPU регистры.
Не могли ли бы вы оценить мой код, посоветовать как можно ещё ускорить его?
Вот проект на D7 - 11Кило
http://www.3ddidactics.nm.ru/FPU.rar
← →
Anatoly Podgoretsky © (2006-08-27 14:15) [1]Мне показалось, что Deplhi не очень оптимизирвано(по скорости)
Чего, какое отношение Дельфи имеет к оптимизации твоего ассемблерного кода?
← →
Anatoly Podgoretsky © (2006-08-27 14:18) [2]У Интела есть документ по оптимизации ассемблера под процессор Пентиум, стоит его прочитать. Кроме того на моем сайте есть две статьи по ассемблеру, одна посвящена именно оптимизации. Может это даст какую ни будь полезную тебе информацию.
Преобразование Дельфи в ассемблер делается по шаблонам, без участия человеческого ума.
← →
имя (2006-08-27 14:23) [3]Удалено модератором
Примечание: Ник смени
← →
Anatoly Podgoretsky © (2006-08-27 14:28) [4]Чапаев носками хакера (27.08.06 14:23) [3]
Не под первый, стоит сначало ознакомиться с первоисточником.
Но у Интела есть и компилятор СИ под конкретный целевой процессор, а ты готов этим пользоваться, если ты не пишешь технологическую систему под конкретное железо?
← →
Anatoly Podgoretsky © (2006-08-27 14:28) [5]И конечно к прочитанному применять голову, а не бездумно.
← →
имя (2006-08-27 14:36) [6]Удалено модератором
Примечание: Ник смени
← →
Evgheni86 (2006-08-27 14:51) [7]> Чего, какое отношение Дельфи имеет к оптимизации твоего ассемблерного кода?
Изначально программа была написана на чистом Object Pascal - без
ассемблерных вставок! Когда я сказал, что Deplhi не слишком оптимизирует
код, то имел ввиду, что, компилируя Object Pascal в машинный код, Delphi
зачастую использует не самые оптимальные варианты и привел яркий тому
пример.
Прграмма будет работать только на PC, Pentium IV 2.6 - под управлением
Windows XP SP1
А за сайт, спасибо :)
← →
Pavia © (2006-08-27 17:40) [8]
> Прграмма будет работать только на PC, Pentium IV 2.6 - под
> управлением
> Windows XP SP1
Хочешь в 10 раз ускорить?
Поставь.
cmp ecx, 255 //Макс. число итераций
← →
Pavia © (2006-08-27 17:43) [9]И чтобы еще в 2 два раза сделать выиграшь используй Scanline
← →
DevilDevil © (2006-08-27 22:07) [10]
> Anatoly Podgoretsky © (27.08.06 14:18) [2]
> Кроме того на моем сайте есть две статьи по ассемблеру,
> одна посвящена именно оптимизации. Может это даст какую
> ни будь полезную тебе информацию.
Анатолий, зашёл на Ваш сайт (фотка справа понравилась :), вышеуказанных статей не нашёл. Вас не затруднит привести ссылки?
← →
Anatoly Podgoretsky © (2006-08-27 22:09) [11]В разделе DDP
← →
DevilDevil © (2006-08-31 00:13) [12]Вот читаю сейчас Христенсена и Гайбелса... всё никак не могу понять:
1) что быстрее:fld X
fld X
fmulp
илиfld X
fmul X
2) что быстрее (для single естественно):fld X
fstp Y
илиmov eax, X
mov Y, eax
3) существует ли возможность избавиться от 4-х лишних команд(используя встроенный ассемблер):push ebp
mov ebp,esp
add esp,-$08
...
pop ebp
4) кто опечатался: Гайбелсом или Галисеев? У Галисееваdec
не изменяет флаг нуля
5) почему стандартныйLOOP
цикл медленне, чем:@@loop:
...
dec ECX
jnz @@loop
6) почему Delphi до сих пор вставляет FWAIT, если надобность в ней отпала с появлением процессоров 80287 ?
7) Допустим в стеке 4 числа [st(0), st(1), st(2), st(3)]. Если выполнитьFFREE st(2)
, то st(3) тоже освободится?
8) Где можно почитать (на русском желательно) про латентность, параллельные вычисления и кеширование?
9) Какой самый быстрый способ сравнить с нулём:TEST reg, reg
,OR reg, 0
или ещё какой-нибудь?
10) почемуpush eax ... pop eax
быстрее, чемpush ax ... pop ax
?
11) Почему Гайбелс пишет: "Битовые инструкции (bt, btc, bts, btr) должны по возможности заменяться на инструкции and, or, xor и test, когда приоритетом является скорость", если по определению bt, btc, bts, btr должны работать в несколько раз быстрее?
12) аналогично с [11] относительноREP MOVS
: "В большинстве случаев, комплексные строковые инструкции очень медленны и должны быть заменены оптимизированным циклом с простыми инструкциями.". Как показывают мои эксперименты,REP MOVS
работают значительно быстрее. Delphi, что примечательно, сама использует их при необходимости присвоить одной переменной-записи другую. Как работает командаMOVS dest, src
?
13) почему для наибыстрейшего кода рекомендуют использовать TASM или MASM, если то же самое удобнее реализовать в Delphi? Какой ассемблер использовать?
← →
default © (2006-08-31 00:23) [13]Удалено модератором
← →
guav © (2006-08-31 00:23) [14]> 3) существует ли возможность избавиться от 4-х лишних команд(используя
> встроенный ассемблер):
Стек фрейм не создаётся, ели параметры уместились в регистрах, а локальных переменных нет. См Assembly procedures and functions
в справке.
> 4) кто опечатался: Гайбелсом или Галисеев? У Галисеева dec
> не изменяет флаг нуля
см. код из следующего пункта :)
← →
guav © (2006-08-31 00:25) [15]> 9) Какой самый быстрый способ сравнить с нулём: TEST reg,
> reg, OR reg, 0 или ещё какой-нибудь?
если книги и моя память не врут, то любой ис or, cmp test в форме op reg, reg
← →
Ketmar © (2006-08-31 00:31) [16]dec не изменяет флаг переноса. %-)
← →
DevilDevil © (2006-08-31 00:34) [17]> guav © (31.08.06 00:23) [14]
если все смещения самому просчитать, то можно обойтись без них [команд]
← →
default © (2006-08-31 00:34) [18]11)
выскажу предположение
bt, ...не ограничиваются аргументами какой-то типовой размерности (32 бита, 64 бита, etc) поэтому из-за этой добавочной функциональности они, возможно, и медленнее
то есть эти команды универсальнее чем and or... а последние за счёт своей специфичности к размеру аргумента и быстрее, всё логично, специфичное быстрее универсального
← →
DevilDevil © (2006-08-31 00:44) [19]> guav © (31.08.06 00:25) [15]
По-моему,CMP
должен медленее работать, т.к. производит арифметическое действие, аOR
иTEST
- логическое
← →
guav © (2006-08-31 00:45) [20]> если все смещения самому просчитать, то можно обойтись без
> них [команд]
Эт понятно, однако они таки вставляются компилятором или не вставляются, в зависимости от ситуациии.
← →
Pavia © (2006-08-31 01:23) [21]Я плохо в оптимизации разбираюсь.
> 2) что быстрее (для single естественно):
> fld X
> fstp Y
> или
> mov eax, X
> mov Y, eax
Скорее всего второй быстрее.
> 4) кто опечатался: Гайбелсом или Галисеев? У Галисеева dec
> не изменяет флаг нуля
Изменяет Flags Affected
The CF flag is not affected. The OF, SF, ZF, AF, and PF flags are set according to the result.
> 5) почему стандартный LOOP цикл медленне, чем:
> @@loop:
> ...
> dec ECX
> jnz @@loop
Это связанно с тем что LOOP сложная команда. Поэтому и не спаривается.
> 6) почему Delphi до сих пор вставляет FWAIT, если надобность
> в ней отпала с появлением процессоров 80287 ?
В первые слышу. и почему 287?
> 8) Где можно почитать (на русском желательно) про латентность,
> параллельные вычисления и кеширование?
На www.wasm.ru перевод Агнера Фога.
> 9) Какой самый быстрый способ сравнить с нулём: TEST reg,
> reg, OR reg, 0 или ещё какой-нибудь?
самый быстрый не сравнивать. Многии команды выставляют флаг нуля. После них можно использовать.
JZ
> 11) Почему Гайбелс пишет: "Битовые инструкции (bt, btc,
> bts, btr) должны по возможности заменяться на инструкции
> and, or, xor и test, когда приоритетом является скорость",
> если по определению bt, btc, bts, btr должны работать в
> несколько раз быстрее?
Потому что для поиска бита нужно сделать цикл. А это сложная команда, которая не спариваются.
> 12) аналогично с [11] относительно REP MOVS: "В большинстве
> случаев, комплексные строковые инструкции очень медленны
> и должны быть заменены оптимизированным циклом с простыми
> инструкциями.". Как показывают мои эксперименты, REP MOVS
> работают значительно быстрее. Delphi, что примечательно,
> сама использует их при необходимости присвоить одной переменной-
> записи другую. Как работает команда MOVS dest, src ?
На разных объемах разные результаты.
На REP тратится один такт при декодирование.
← →
Pavia © (2006-08-31 01:30) [22]
> По-моему, CMP должен медленее работать, т.к. производит
> арифметическое действие, а OR и TEST - логическое
Нет ADD SUB CMP OR TEST занимают одинаковое число таков. Это связанно с тем что это простые команды. И довольно просто реализуются в кремпие.
← →
default © (2006-08-31 01:32) [23]Pavia © (31.08.06 01:23) [21]
> 11) Почему Гайбелс пишет: "Битовые инструкции (bt, btc,
> bts, btr) должны по возможности заменяться на инструкции
> and, or, xor и test, когда приоритетом является скорость",
> если по определению bt, btc, bts, btr должны работать в
> несколько раз быстрее?
Потому что для поиска бита нужно сделать цикл. А это сложная команда, которая не спариваются.
какой простите нахрен цикл?
← →
Pavia © (2006-08-31 01:42) [24]Для установки бита требуетс Взять бит сделать сдвиг в лево установить бит.
SHL SHR это цикличиские команды, так их реализуют в кремние.
Для установки бита нужно выполнить две микро инструкции
SHLl r,1,imm -
and rr,r
Раз две значит команда не спаривается.
← →
default © (2006-08-31 01:46) [25]Pavia © (31.08.06 01:42) [24]
вот, например, для получения значения бита достаточно сделать and и воспользоваться флагом нуля(насколько помню and работает с флагом нуля)где здесь цикл?
← →
Pavia © (2006-08-31 01:49) [26]А том и речь. Поэтому и советуют использовать
AND r,1 shl imm
Здвиг выполняется при компиляции
BT R, imm
Здвиг выполняется при выполнение команды.
← →
Pavia © (2006-08-31 02:14) [27]Давай еще раз по порядку. Просто есть у меня причуда начинать не с начала, а с конца.
Для установки бита требуется. Взять бит, сделать сдвиг в лево, установить бит.
AND r,1 shl imm
Сдвиг выполняется при компиляции
BTС R, imm
Сдвиг выполняется при выполнение команды. И представляет из себя две микро команды
SHL RR, 1, imm сдвинуть 1 в лево занести результат в RR вспомогательную ячейку (регистр)
AND R, RR
SHL – это сдвиг, но это не так просто сделать сдвиг мы не можем за один раз сделать произвольное число сдвигов. Мы можем за раз сделать только 1. Это ограничение физическое связанное с реализацией сдвига в кремнии. Отсюда и цикл. Отсюда и летальность команды.
Я многое знаю, про процессор. Но вот все по полочкам разложить не успел. Так что извините, если что не так. Я спать.
← →
DevilDevil © (2006-08-31 10:31) [28]> Pavia © (31.08.06 01:30) [22]
По результатам моих тестов,CMP
медленне, чемOR
> 6) почему Delphi до сих пор вставляет FWAIT, если надобность
> в ней отпала с появлением процессоров 80287 ?
В первые слышу. и почему 287?
Данные из книги В. Пирагова
> На разных объемах разные результаты.
> На REP тратится один такт при декодирование.
По идее, чем больше, темREP...
быстрее.
Как работает командаMOVS dest, src
?
← →
Lamer@fools.ua © (2006-08-31 12:09) [29]>>Evgheni86 (27.08.06 14:12)
>Мне показалось, что Deplhi не очень оптимизирвано(по скорости)
использует FPU и работает с Real числами Например
Объявлены две Real переменные a и b(локалки)
Если мы напишем a:=b, то в диззассемблере
это будет выглядеть так:
...
Оптимизация была включена?
← →
Pavia © (2006-08-31 17:35) [30]
> По результатам моих тестов, CMP медленне, чем OR
Тесты в студию у меня равны.
const N=1000000000;
var t1,t2:int64;
i:Integer;
begin
asm
RDTSC
mov DWord[t1],eax
mov DWord[t1+4],edx
end;
For i:=0 to N do
begin
asm
OR ax,0 // подопытный
end;
end;
asm
RDTSC
mov DWord[t2],eax
mov DWord[t2+4],edx
end;
edit2.Text:=FloatToStr((t2-t1)/N);
end;
> 6) почему Delphi до сих пор вставляет FWAIT, если надобность
> в ней отпала с появлением процессоров 80287 ?
В первые слышу. и почему 287?
Данные из книги В. Пирагова
Этой книги нет. Но на верника там было написанно, что НЕКОТОРЫЕ функции сопроцессора не нуждаются в FWAIT. И то начиная с 486 и Pentium.
Вот почитай там и про REP MOVS и про FWAIT и про LOOP.
http://www.wasm.ru/article.php?article=1010027
И другии главы тоже.
← →
DevilDevil © (2006-08-31 19:01) [31]> Этой книги нет.
Правильно. И меня нет. И тебя, кстати тоже... всё..., всё что мы видим - THE MATRIX...
За ссылки спасибо, вот сижу почитываю.
Вопросов осталось меньше.
Самый быстрый способ проверить на 0 -TEST eax, eax
push eax ... pop eax
быстрее, чемpush ax ... pop ax
потому что шина 32-битная. Выполняя 16-битные операции, лишнее время тратится на "обрезание" параметров.
Ну с проверкой наличия заведомо известного номера бита понятно:TEST eax, 8
(бит номер 3), а если на i-й бит проверить, как быстрее BT или:MOV edx, 1
SHL edx, i
TEST eax, edx
7) Допустим в стеке 4 числа [st(0), st(1), st(2), st(3)]. Если выполнитьFFREE
st(2), то st(3) тоже освободится?
13) почему для наибыстрейшего кода рекомендуют использовать TASM или MASM, если то же самое удобнее реализовать в Delphi? Какой ассемблер использовать? Зачем много проходов?
← →
DevilDevil © (2006-08-31 19:20) [32]Самый быстрй способ возвести в квадрат?
Посмотрел, Delphi вместо sqr генерит:fld X
fmul st(0)
Начнём с того, что мои попытки использовать явно какой-либо элемент стека не увенчались успехом. Решил попробовать простоfmul
, может он по умолчанию генерит то, что нужно:function Kvad(X : double) : double;
asm
fld X;
fmul
end;
Ну тут то было. Генерит опfmulp st(1)
. Чё за ерунда?
← →
DevilDevil © (2006-09-02 15:19) [33]Самый быстрый способ возвести в квадрат:
function Kvad(X : double) : double;
asm
fld X;
fmul st(0), st(0)
end;
Причём строкаfmul st(0), st(0)
в дизассемблере будет выглядеть какfmul st(0)
Решил попробовать себя в TASM, написал ту же самую функцию:
KVADRAT PROC; function (X : single) : single;
fld dword ptr [esp+8h]
fmul st(0), st(0)
ret 4h
KVADRAT ENDP
Попробовал..... В общем столкнулся я с проблемой, которая НУ ОЧЕНЬ мне не понятна. Если оставить процедуру в таком варианте, то результат НЕПРАВИЛЕН. А если сделать например так, то всё путём:
KVADRAT PROC; function (X : single) : single;
push eax
fld dword ptr [esp+8h]
fmul st(0), st(0)
pop eax
ret 4h
KVADRAT ENDP
Буду очень признателен, если объяснят, что же произошло...
P.S. Говорят программист на Си должен знать Си и ассемблер. Программист на Delphi должен знать Си, Delphi и ассемблер... Похоже на всём форуме программистов на Delphi можно пересчитать по пальцам...
← →
Anatoly Podgoretsky © (2006-09-02 15:29) [34]DevilDevil © (31.08.06 00:13) [12]
Слишком много сразу вопросов.
На вопрос, что быстрее ответить профилировщик, но на разных процессорах, могут быть разные результаты.
На вопрос об избавлении от лишних команд, иногда наоборот добавление лишних комант NOP дает ускорение, хотя это и против логики.
← →
Anatoly Podgoretsky © (2006-09-02 15:32) [35]Оптимизация это сложная вещь, кто тому же не дерминированая, зависит от процессора.
Вроде бы только у Интела есть оптимизированый компилятор С++, который может настраиваться на процессор. Но написание таких программ имеет мало смысла для коммерческого применения, только под конкретную технологическую установку и то при условии, что процессор никогда не будет меняться.
← →
Virgo_Style © (2006-09-02 15:37) [36]Anatoly Podgoretsky © (02.09.06 15:32) [35]
Оптимизация это сложная вещь, кто тому же не дерминированая
так это ж хорошо, если не... того... на букву Д... %-)
← →
default © (2006-09-02 16:04) [37]DevilDevil © (02.09.06 15:19) [33]
"KVADRAT PROC ; function (X : single) : single;
fld dword ptr [esp+8h]
fmul st(0), st(0)
ret 4h
KVADRAT ENDP"
замени на
KVADRAT PROC ; function (X : single) : single;
fld dword ptr [esp+4h]
fmul st(0), st(0)
ret 4h
KVADRAT ENDP
"Программист на Delphi должен знать Си, Delphi и ассемблер... Похоже на всём форуме программистов на Delphi можно пересчитать по пальцам..."
вот только подобные высказывания оставляй впредь при себе(это я совсем не про себя)
← →
Pavia © (2006-09-02 16:22) [38]
> добавление лишних комант NOP дает ускорение, хотя это и
> против логики.
Насколько я слышил это заметно на pentium III.
> Причём строка fmul st(0), st(0) в дизассемблере будет выглядеть
> как fmul st(0)
Потому что это один и тот же опкод. Просто st(0) подрозумевается.
← →
Anatoly Podgoretsky © (2006-09-02 16:27) [39]Pavia © (02.09.06 16:22) [38]
> добавление лишних комант NOP дает ускорение, хотя это и
> против логики.
Насколько я слышил это заметно на pentium III.
Правильно, и не только и это подтверждает, что нет абсолютного понятия Оптимизация, то что хорошо работало на 8086-80486 не обязано работать на P1, P2, P3 и далее и в будущем. Наглядный случай аггрегатные операции, которые провалились на Пентиумах.
← →
Alx2 © (2006-09-02 18:01) [40]>Anatoly Podgoretsky © (02.09.06 15:32)
> и то при условии, что процессор никогда не будет меняться.
Это да. Но они также сделали возможность генерации кода под линейку процессоров. Стартовый код определяет процессор, после чего вызывается заточенный под него main со всеми вытекающими.
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2006.09.24;
Скачать: [xml.tar.bz2];
Память: 0.58 MB
Время: 0.039 c