Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.01.19;
Скачать: CL | DM;

Вниз

Интересная задача. Остаток от деления умножением   Найти похожие ветки 

 
DevilDevil ©   (2013-07-29 15:21) [40]

> Rouse_ ©   (29.07.13 14:44) [35]
> Оть тебе компилятор от MS

Оть тебе GCC

int DLL_EXPORT IntTest(int X)
{
 return X / 3;
}

mov     ecx, [esp+arg_0]
mov     edx, 55555556h
mov     eax, ecx
imul    edx
sar     ecx, 1Fh
sub     edx, ecx
mov     eax, edx
retn

unsigned DLL_EXPORT DwordTest(unsigned X)
{
 return X /  3;
}

mov     edx, 0AAAAAAABh
mov     eax, [esp+arg_0]
mul     edx
shr     edx, 1
mov     eax, edx
retn


 
Rouse_ ©   (2013-07-29 15:27) [41]


> DevilDevil ©   (29.07.13 15:21) [40]

А смысл то какой? Дельфя всеравно все будет по старинке генерировать.


 
DevilDevil ©   (2013-07-29 15:31) [42]

> Rouse_ ©   (29.07.13 15:27) [41]

> А смысл то какой? Дельфя всеравно все будет по старинке
> генерировать.


нет, если заменять деление на умножение со сдвигом
или перейти на асм

тут суть не в том, чтобы обязательно применять в жизни. Суть в том, чтобы как минимум знать, как это можно применить на практике. Не всё же водопровод обсуждать, можно и программистскими задачками на этом форуме заняться


 
Rouse_ ©   (2013-07-29 16:14) [43]


> Суть в том, чтобы как минимум знать, как это можно применить
> на практике.

Практического применения не имеет, ну разве ты не соберешся свой собственный компилятор реализовать, а если просто заменить деление в коде - достаточно через asm вставку произвести изменения, раз уж так хочется.
Тратить-же рабочее время в пустую, пытаясь оптимизировать все и вся - есть очень плохой подход к разработке ПО.


 
DevilDevil ©   (2013-07-29 16:31) [44]

Ни в коем случае не нужно оптимизировать всё и вся. Очевидно, бывают задачи, в которых приходится обрабатывать большой объём данных и производить различные вычисления, такие как деление например. Приведённый мной код сводит 30 тактное деление к операциям в 6 (ну 7-8 максимум) тактов. Говорить, что оптимизировать деление в программах не нужно - достаточно опрометчиво; ибо операция распространённая и отжирает немеряно тактов.

> а если просто заменить деление в коде - достаточно через
> asm вставку произвести изменения, раз уж так хочется.


в [31] как раз и поднят этот вопрос. Ибо что именно писать в "asm вставку" общественности не известно :). Можно конечно скомпилировать хорошим С++ компилятором и посмотреть у него в дизассемблере... но как то это не по мастерски что ли. Имхо


 
Павиа   (2013-07-29 16:35) [45]

Во первых твои ответы легко гуглится.
Что касается замены сдвигов, то оно всем известно. И где надо используется.
Вот только там где надо это это от силы один случай из 1000.
Преждевременная оптимизация это зло в квадрате.


 
Inovet ©   (2013-07-29 16:37) [46]

Меня как-то занимал вопрос. Вот есть деление по модулю и целочисленное деление. Почему нет конструкции для получения результатов этих двух двух операций вместе, раз уж они одной процессорной инструкцией реализованы, да и не только инструкцией - по логике деления остаток всё равно где-то хранится.

Ну, нестандартая конструкция нужна, видимо, поэтому забили.


 
Inovet ©   (2013-07-29 16:40) [47]

> [44] DevilDevil ©   (29.07.13 16:31)
> общественности не известно :).

Ладно, смайлик стоит. Сочтём за юмор.


 
DevilDevil ©   (2013-07-29 16:42) [48]

> Павиа   (29.07.13 16:35) [45]
> Во первых твои ответы легко гуглится.


ну так скопируй из гугла да приведи сюда
чтобы эти "формулы" не имели погрешностей; чтобы результат деления эмулировался однозначно

> Что касается замены сдвигов, то оно всем известно. И где надо используется.
> Вот только там где надо это это от силы один случай из 1000.


действительно на практике деления на степень двойки редки
но о них никто здесь не говорит, если ты внимательно почитаешь

> Преждевременная оптимизация это зло в квадрате.
а современные конвейеры выполняют div за три такта
знаем, слышали :)


 
Павиа   (2013-07-29 16:43) [49]


> Почему нет конструкции для получения результатов этих двух
> двух операций вместе

Как это нету в модуле math лежит если не путаю divmod


 
DevilDevil ©   (2013-07-29 16:44) [50]

> Inovet ©   (29.07.13 16:37) [46]
> Меня как-то занимал вопрос. Вот есть деление по модулю и
> целочисленное деление. Почему нет конструкции для получения
> результатов этих двух двух операций вместе, раз уж они одной
> процессорной инструкцией реализованы, да и не только инструкцией
> - по логике деления остаток всё равно где-то хранится.


справку надо читать, а не курить
div возвращает и частное и остаток

> Inovet ©   (29.07.13 16:40) [47]
> Ладно, смайлик стоит. Сочтём за юмор.


даже не знаю как комментировать :)
может ты просто не понял вопрос ?


 
Павиа   (2013-07-29 16:48) [51]


> а современные конвейеры выполняют div за три тактазнаем,
>  слышали :)

Нет больше 9 но меньше 30.


> чтобы эти "формулы" не имели погрешностей; чтобы результат
> деления эмулировался однозначно

http://www.agner.org/optimize/optimizing_assembly.pdf
страница 140. В интернетах есть и русский перевод.


 
DevilDevil ©   (2013-07-29 16:49) [52]

> Павиа   (29.07.13 16:43) [49]

> Как это нету в модуле math лежит если не путаю divmod


да, но он убогий
возвращает только word-ы если не ошибаюсь
вообще мне кажется компилятор сам должен распознавать ситуации, когда в коде рядом располагаются и div и mod на одних и тех же операндах


 
Павиа   (2013-07-29 16:50) [53]


> даже не знаю как комментировать :)может ты просто не понял
> вопрос ?

Таки по поводу труб. Текут сегодня должны были почсенить. Но что-то мне не нравиться как счётчик поставили так течь начали. Уже 2 раз сантехника вызываем.


 
DevilDevil ©   (2013-07-29 17:00) [54]

> http://www.agner.org/optimize/optimizing_assembly.pdf
> страница 140. В интернетах есть и русский перевод.


неплохая отправная точка
когда я листал этот документ - увидел только оптимизации с плавающей точкой
но там муторно написано. используется shr вместо sar, imul вместо mul (для unsigned). Милости прошу - отвечай на вопрос [31]. Будем тестировать


 
Inovet ©   (2013-07-29 17:07) [55]

> [49] Павиа   (29.07.13 16:43)
> divmod

Не, то процедура ещё и асм, теряется весь смысл. Надо,чтобы по месту работало типа инлайн бы была.


 
Inovet ©   (2013-07-29 17:11) [56]

> [50] DevilDevil ©   (29.07.13 16:44)
> div возвращает и частное и остаток

Ты о каком div?


 
Inovet ©   (2013-07-29 17:11) [57]

> [50] DevilDevil ©   (29.07.13 16:44)
> может ты просто не понял вопрос ?

Всё я понял.


 
Inovet ©   (2013-07-29 17:13) [58]

Я вот как раз сейчас услышал один принцип:
"Принцип Боба. Когда у Боба есть проблемы со всеми, главной проблемой обычно является сам Боб."


 
DevilDevil ©   (2013-07-29 17:21) [59]

> Павиа
> Таки по поводу труб. Текут сегодня должны были почсенить.
>  Но что-то мне не нравиться как счётчик поставили так течь
> начали. Уже 2 раз сантехника вызываем.


> Нет больше 9 но меньше 30.

http://www.agner.org/optimize/instruction_tables.pdf

у Bobcat mul/imul от 1 до 4 тактов. div/idiv - от 27 до 81
Sandy Bridge: 1-2 и 11-84 соответственно

а в каком мануале ты видел, что меньше 30 ?
не в инструкции к счётчику воды случайно ?


 
DevilDevil ©   (2013-07-29 17:30) [60]

> Inovet ©   (29.07.13 17:07) [55]
>
> Не, то процедура ещё и асм, теряется весь смысл. Надо,чтобы
> по месту работало типа инлайн бы была.


Вот как это выглядит в цивилизованных компиляторах

int DLL_EXPORT DivModTest(int X, int Y)
{
   return (X / Y) + (X % Y);
}

mov     eax, [esp+arg_0]
cdq
idiv    [esp+arg_4]
add     eax, edx
retn


 
Sapersky   (2013-07-29 17:46) [61]

84 такта - это r64... вроде редко нужно делить что-то именно 64-битное.

DIVPS (SSE) - 10-14 тактов, 4 числа за раз, в расчёте на 1 число около 3 тактов.
RCPPS (приближённое 1/x) - 5 тактов, хотя мне в единственном случае применения точности как раз не хватило.

Понятно, что если алгоритм уже заточен под целые, то SSE с плавающей точкой вряд ли имеет смысл, конверсия форматов здорово испортит (а то и вообще убьёт) всё ускорение. С другой стороны, возможно, это повод пересмотреть формат данных:
http://blog.lexa.ru/2011/08/27/o_legacy_i_formatakh_dannykh.html


 
DevilDevil ©   (2013-07-29 17:52) [62]

> Sapersky   (29.07.13 17:46) [61]

ну так целочисленное деление не равно делению с плавающей точкой
в таком случае вообще делается UN_DIV_CONST = 1/const
вообще без операций деления

и зачем конвертировать alu <--> fpu, когда уже тысячу лет придумали оптимизированное целочисленное деление на константу. По сути ветка является только детализацией этого механизма, чтобы и мы при желании могли им воспользоваться в своих Delphi-проектах


 
Sapersky   (2013-07-29 19:41) [63]

А что тут детализировать...
Шаманский метод вроде [40] - это конечно замечательно, но если компилятор не поддерживает, нужно каждый раз высчитывать магические числа вручную, и ещё прикидывать какие-то исключения, с которыми это не будет работать.
Уж проще тогда написать UN_DIV_CONST = 65536 div const + умножение со сдвигом, а не хватит точности - пусть будет div, и пофиг сколько тактов.

А если переложить высчитывание магических чисел на комп, то это оправдывается, только если нужно делить массив чисел на одно и то же. У Агнера Фога [51] там дальше есть ссылка на его библиотечку с подобными функциями. Вот это в принципе имеет смысл, можно попробовать... правда делить массив на одно число нужно не так уж и часто.


 
Inovet ©   (2013-07-29 19:49) [64]

> [60] DevilDevil ©   (29.07.13 17:30)
> Вот как это выглядит в цивилизованных компиляторах
>
> int DLL_EXPORT DivModTest(int X, int Y)
> {
>   return (X / Y) + (X % Y);
> }
>
> mov     eax, [esp+arg_0]
> cdq
> idiv    [esp+arg_4]
> add     eax, edx
> retn


Вот как это выглядит в Builder XE4

struct tdiv_test
{
 int quot;
 int rem;
 tdiv_test(int q, int r) {quot = q; rem = r;}
};

inline __fastcall tdiv_test div_test(int num, int div)
{
 return tdiv_test(num / div, num & div);
}

int __fastcall DivModTest(int n, int d)
{
 return n / d + n % d;
}

int __fastcall DivModTest2(int n, int d)
{
 tdiv_test t = div_test(n, d);
 return t.quot + t.rem;
}

@DivModTest$qqrii segment virtual
align 2
@@DivModTest$qqrii proc near
?live16385@0:
@1:
push      ebx
push      esi
mov       ebx,edx
mov       ecx,eax
?live16385@16: ; ECX = n, EBX = d
mov       eax,ecx
cdq
idiv      ebx
mov       esi,eax
mov       eax,ecx
cdq
idiv      ebx
add       esi,edx
mov       eax,esi
?live16385@32: ;
@3:
@2:
pop       esi
pop       ebx
ret
@@DivModTest$qqrii endp
@DivModTest$qqrii ends
_TEXT ends

_TEXT segment dword public use32 "CODE"
@DivModTest2$qqrii segment virtual
align 2
@@DivModTest2$qqrii proc near
?live16386@0:
@4:
push      ebx
push      esi
add       esp,-8
?live16386@16: ; EAX = n, EDX = d
mov       ecx,eax
mov       ebx,edx
mov       esi,ebx
and       esi,ecx
mov       eax,ecx
cdq
idiv      ebx
mov       dword ptr [esp],eax
mov       eax,esi
mov       dword ptr [esp+4],eax
?live16386@32: ; EAX = @temp4
mov       edx,dword ptr [esp]
add       edx,eax
mov       eax,edx
?live16386@48: ;
@6:
@5:
pop       ecx
pop       edx
pop       esi
pop       ebx
ret
@@DivModTest2$qqrii endp
@DivModTest2$qqrii ends


 
Inovet ©   (2013-07-29 20:19) [65]

> [64] Inovet ©   (29.07.13 19:49)
> return tdiv_test(num / div, num & div);

А чёрт. Думаю - что за фигня, а оно вон что. Вот так правильно

 return tdiv_test(num / div, num % div);

_TEXT segment dword public use32 "CODE"
@DivModTest2$qqrii segment virtual
align 2
@@DivModTest2$qqrii proc near
?live16386@0:
@4:
push      ebx
push      esi
add       esp,-8
?live16386@16: ; EAX = n, EDX = d
mov       ecx,eax
mov       ebx,edx
mov       eax,ecx
cdq
idiv      ebx
mov       esi,edx
mov       eax,ecx
cdq
idiv      ebx
mov       dword ptr [esp],eax
mov       eax,esi
mov       dword ptr [esp+4],eax
?live16386@32: ; EAX = @temp4
mov       edx,dword ptr [esp]
add       edx,eax
mov       eax,edx
?live16386@48: ;
@6:
@5:
pop       ecx
pop       edx
pop       esi
pop       ebx
ret
@@DivModTest2$qqrii endp
@DivModTest2$qqrii ends
_TEXT ends

Короче, результат не радует. Это с дефолтными установками компилятора на Release, только отключена динамическая RTL, но здесь это пофиг.


 
Jeer ©   (2013-07-29 20:34) [66]

TC - "Очередной метр".


 
Inovet ©   (2013-07-29 20:39) [67]

> [66] Jeer ©   (29.07.13 20:34)
> "Очередной метр".

Я бы даже сказал - метроном.:)


 
DevilDevil ©   (2013-07-29 21:13) [68]

> Sapersky   (29.07.13 19:41) [63]

> Шаманский метод вроде [40] - это конечно замечательно, но
> если компилятор не поддерживает, нужно каждый раз высчитывать
> магические числа вручную


об том и речь

> и ещё прикидывать какие-то исключения, с которыми это не
> будет работать.


не
суть как раз в том, что если делать грамотно - он сработает для любых констант на любом диапазоне чисел (в рамках integer/cardinal конечно). А если подходить упрощено типа 2^16 - тогда естественно погрешность будет. Но зачем, если можно эмулировать деление один в один

> А если переложить высчитывание магических чисел на комп,
>  то это оправдывается, только если нужно делить массив чисел
> на одно и то же.


не мне тебе рассказывать, что такое такты. Если в твоём цикле 3 деления реализованы рассматриваемым способом - это уже 90+ тактов экономии на одну итерацию. Взять тот же IntToStr - много делений (в последних версиях на 100).

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


 
DevilDevil ©   (2013-07-29 21:15) [69]

> Inovet ©   (29.07.13 20:19) [65]

> Короче, результат не радует. Это с дефолтными установками
> компилятора на Release, только отключена динамическая RTL,
>  но здесь это пофиг.


ну что и требовалось доказать
не понятно только, зачем тебе целая структура для двух значений
используй Point )))


 
DevilDevil ©   (2013-07-29 21:16) [70]

Удалено модератором


 
Jeer ©   (2013-07-29 21:20) [71]

Удалено модератором


 
Jeer ©   (2013-07-29 21:22) [72]

Удалено модератором


 
DevilDevil ©   (2013-07-29 21:24) [73]

Удалено модератором


 
Rouse_ ©   (2013-07-29 23:10) [74]


> Jeer ©   (29.07.13 21:22) [72]

Сергей Батькович, ну ё мае...
Предвижу закрытие ветки...


 
Jeer ©   (2013-07-29 23:12) [75]

>Сергей Батькович

Не.. я затих:)
Пусть меряет дальше спокойно.


 
DevilDevil ©   (2013-07-29 23:16) [76]

> Rouse_ ©   (29.07.13 23:10) [74]
> Предвижу закрытие ветки...

сейчас то что не так ?


 
Jeer ©   (2013-07-29 23:45) [77]

>сейчас то что не так ?

Все нормально.
"Работа мозгом, нежели поршнями, дает больше шансов на повышение интеллекта"

P.S.
Я тоже доставал старших "глупостями", а потом - они становились в очередь за работой ко мне.


 
DevilDevil ©   (2013-07-30 00:32) [78]

> Jeer ©   (29.07.13 23:45) [77]

если ты хочешь чтобы я или иной участник форума тебя похвалил - тебе следует создать собственную ветку


 
DevilDevil ©   (2013-07-30 01:17) [79]

> Sapersky   (29.07.13 19:41) [63]
> У Агнера Фога [51] там дальше есть ссылка на его библиотечку
> с подобными функциями.


да, забавно
думаю взять их за основу, только адаптировать под привычный нам register, а не cdecl :)

смотрю исходники и не могу понять смысл действия
можешь объяснит, что происходит ?

 bsr     ecx, ebx               ; floor(log2(d-1))
 ...
 // ахтунг ахтунг
 inc     ecx                    ; L = ceil(log2(d))        
 sub     ecx, 1                 ; shift count = L - 1
 adc     ecx, 0                 ; avoid negative shift count


как ecx может получиться отрицательный - я чёт не понимаю


 
Sapersky   (2013-07-30 17:40) [80]

Прямо перед bsr строчка:
mov ecx, -1  ; value for bsr if ebx = 0 (assuming bsr leaves dest unchanged if src = 0)
то есть странное телодвижение inc ecx/sub ecx/adc ecx - исключительно для обработки этого случая, чтобы привести ecx к 0.
Хотя в функции предварительного расчёта можно было и явный тест/джамп воткнуть, но автор как настоящий хакер не может не выпендриться...



Страницы: 1 2 3 вся ветка

Текущий архив: 2014.01.19;
Скачать: CL | DM;

Наверх




Память: 0.66 MB
Время: 0.013 c
2-1363871559
tp7
2013-03-21 17:12
2014.01.19
ProcessMessages в DLL


15-1375043600
Petr
2013-07-29 00:33
2014.01.19
DB/2. ацтой или рай?


15-1374908638
Пит
2013-07-27 11:03
2014.01.19
Сумасшедший радиоуправляемый вертолет


15-1373539892
[ВладОшин]
2013-07-11 14:51
2014.01.19
нечеткий custom датасет


15-1375128275
Jeer
2013-07-30 00:04
2014.01.19
С прошедшим Днем ВМФ - мореманов!