Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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.043 c
15-1156495509
Stexen
2006-08-25 12:45
2006.09.24
МКАД


10-1123447573
r4dx
2005-08-08 00:46
2006.09.24
TWebBrowser и AutoSize


4-1146608062
vidiv
2006-05-03 02:14
2006.09.24
"Виртуальный" файл


2-1157571270
redlord
2006-09-06 23:34
2006.09.24
моргание Timage при refresh


9-1112300436
Pa5ha
2005-04-01 00:20
2006.09.24
Вопросы по OpenGL





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский