2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3, 4, 5  След.
 
 Возведение в квадрат в компьютерах.
Сообщение22.05.2019, 16:47 


03/10/06
826
Возведение в квадрат
$$(A_{1} + 2^{k}A_{2})^2 = A_{1}^2 + 2^{k+1}A_{1}A_{2} + 2^{2k}A_{2}^2$$
сводится к трем умножениям чисел половинной длины.

Метод умножения Карацубы
$$A=A_{1}+2^{k}A_{2},\quad B=B_{1}+2^{k}B$$$$AB=A_{1}B_{1}+2^{k}{\Big (}(A_{1}+A_{2})(B_{1}+B_{2})-(A_{1}B_{1}+A_{2}B_{2}){\Big )}+2^{2k}A_{2}B_{2}$$
состоит в том, что четыре умножения сводятся к трём.

Правильно ли я понимаю, что для процессора не программируют возведение в квадрат, а используют тот же метод, что для перемножения разных чисел? Для них же используют метод умножения Карацубы.

код: [ скачать ] [ спрятать ]
Используется синтаксис Pascal
function km(a:integer; b:integer):integer;#karatsuba method
var l1,l2,r,d,d2,al,ar,bl,br:integer;
begin
 l1:=bit_length(a);
 if l1<2 then return a*b; end;
 l2:=bit_length(b);
 if l2<2 then return a*b; end;
 d:=max(l1,l2);
 d2:=bit_shift(d,-1);
 al:=bit_shift(a,-d2);
 ar:=a-bit_shift(al,d2);
 bl:=bit_shift(b,-d2);
 br:=b-bit_shift(bl,d2);
 l1:=km(al, bl);
 l2:=km(ar, br);
 r:=km(al+ar, bl+br);
 r := bit_shift((r-(l1+l2)),d2)+bit_shift(l1,bit_shift(d2,1))+l2;
 return r;
end.


Подумал и запрограммировал некий способ возведения в квадрат в функцию sq(n). И получилось, что он работает заметно быстрее. Обе функции дают одинаковый результат в результате исполнения.
Код:
for n:=1 to 1000000 do
if sq(n)<>km(n,n) then
  writeln(n," sq<>km");
end;
end.
Вывода строки "sq<>km" тут не случилось.
Результаты:
Код:
==> t := timer();m:=0;
for n:=1 to 1000 do
m:=2*m+1;
s:=km(m,m);
end;
writeln(timer()-t).
80414
-: 1

==> t := timer();m:=0;
for n:=1 to 1000 do
m:=2*m+1;
s:=sq(m);
end;
writeln(timer()-t).
550
-: 1

==> 80414/550.
-: 146.207273
При перемножении чисел Мерсенна более чем в 100 раз быстрее.
Код:
==>t := timer();
for n:=1 to 1000000 do
s:=km(n,n);
end;
writeln(timer()-t).
226362
-: 1

==> t := timer();
for n:=1 to 1000000 do
s:=sq(n);
end;
writeln(timer()-t).
10344
-: 1

==> 226362/10344.
-: 21.8834107
При перемножении последовательных чисел более чем в 20 раз быстрее.
Код и проверка сделаны на Aribas ( http://progopedia.ru/language/aribas/ ).
Возможно, что неправильно запрограммировал метод умножения Карацубы и поэтому разрыв в скорости.
Предлагаю желающим попробовать сочинить две функции и повторить эти опыты с возведением в квадрат в любой из систем. Удастся ли вам повторить эти результаты?

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 10:48 
Заслуженный участник


26/05/14
981
Возведение в квадрат и умножение должны отличаться по времени исполнения не более чем в константное число раз. Ваши примеры очень маленькие. Попробуйте числа вида $10^n$, где $n$ достаточно велико чтобы время вычисления было порядка секунды. Варьируя $n$ получите несколько времён, затем восстановите регрессией константу $C$ и степень $a$ в формуле $Cn^a$.

integer тип из ARIBAS может оказаться неудачным контейнером для чисел. Алгоритм Карацубы рассчитан на работу с массивами ограниченных целых. Вы используете integer, следовательно вам надо проверять что элементарные операции (умножение на степень двойки, сложение) у вас имеют ту же сложность что и операции над массивами бит/ограниченных целых.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 12:52 


03/10/06
826
На чем поэкспериментировать, может Питон, там вроде бы целый тип не ограничен? В Арибас есть ограничение по целым числам.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 13:02 
Заслуженный участник


26/05/14
981
Питон подойдёт, там нормальные неограниченные целые.
В Арибас я прочитал что числа не ограничены. Ошибся?

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 13:06 
Заслуженный участник


04/03/09
906
В питоне, а точнее, в cpython, уже используется алгоритм Карацубы при умножении больших целых чисел. Реализуйте лучше сами класс BigInteger, и на нем сравнивайте умножения.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 13:13 
Заслуженный участник
Аватара пользователя


16/07/14
8458
Цюрих
Тут вопрос в том, какая у вас реализация sq. Для одиночных чисел, квадрат которых влезает в регистры (скорее всего до $2^31 - 1$ в вашей реализации) ничего быстрее прямого умножения (которое скомпилируется в одну инструкцию) сделать не удастся. Для многих чисел нужно умножать пачками (и придется руками перемножать отдельные 32 битные части). Никакие софтверные реализации тут в любом случае не помогут.

Внутри для умножения используются схемы логарифмической глубины (зато с большим числом элементов), так что "асимптотика" умножения двух $n$-битных чисел - $O(\log n)$. Разумеется это утверждение особого смысла не имеет, т.к. на практике у нас одна схема, а не набор схем под каждую разрядность.

Код имеет смысл писать для перемножения длинных чисел (не влезающих в регистры). И тут какие-то оптимизации для возведения в квадрат по сравнению с умножением Карацубы могут иметь смысл. Но т.к. обычное умножение векторизуется сильно лучше, чем умножение Карацубы, скорее всего есть смысл сделать несколько итераций умножения Карацубы, а потом обычное.
Для достаточно длинных чисел (сотни тысяч разрядов) вообще лучше брать метод Шёнхаге-Штрассена (к сожалению его реализовать на "верхних уровнях" с переключением на обычное умножение внизу нельзя).

Встроенную в питон реализацию длинных чисел вы на питоне не обгоните никак. И вообще такие вещи замерять на питоне - странная затея. Логичнее реализовать длинную арифметику самостоятельно, и сравнить, насколько в одной и той же реализации будет отличаться специализированное и общее возведение в квадрат.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 13:49 
Заслуженный участник


26/05/14
981
mihaild, в Питоне не лучшая реализация длинной арифметики. Там Карацуба, а не Шёнхаге-Штрассен, а GNU MP они оба. Печатает Питон длинные числа вообще за квадрат.
Как я понял ТС, он будет использовать длинные целые только для хранения, сложения, умножения на степень двойки, умножения произвольных чисел с ограниченной длиной в битах. При должной аккуратности можно смоделировать Карацубу довольно точно. Идея ведь реализовать возведение в квадрат и умножение и сравнить их О-большие, не более.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение23.05.2019, 14:58 
Заслуженный участник
Аватара пользователя


30/01/06
72407
yk2ru в сообщении #1394590 писал(а):
Правильно ли я понимаю, что для процессора не программируют возведение в квадрат, а используют тот же метод, что для перемножения разных чисел?

Если имеются в виду инструкции процессора, то да, повсеместно есть инструкции умножения, и нигде не встречал инструкции возведения в квадрат.

Обычное дело - инструкция извлечения квадратного корня. Возведения в целочисленную степень не бывает. Странно, но не делают и извлечения кубического корня. Вообще возведение в произвольную степень реализуется через трансцендентные функции $2^x$ и $\operatorname{lb}(x)=\log_2 x.$ На трансцендентных функциях экономят (по числу функций, а не по скорости выполнения, при том что они обычно медленные): часто встречается набор $\sin,\cos,\operatorname{atan}_2,$ а остальные - делайте из них сами. (Правда, этот выбор может быть обусловлен и тем, что это "самые хорошие" функции по области определения и всяким особенностям.)

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение25.05.2019, 15:39 


03/10/06
826
Код sq не содержит рекурсий, возможно поэтому работал быстрее. На длинных числах будет в два раза быстрее обычного умножения столбиком, как я понимаю. Возможна оптимизация, не на каждом нуле устраивая сдвиги, а потом на единице скопом. И в конце только результат вычислять.
код: [ скачать ] [ спрятать ]
Используется синтаксис Pascal
function sq(a:integer):integer;
var al,b,n,r:integer;
begin
 if a<2 then
  return a*a;
 end;
 r:=1; al:=1;
 n:=bit_length(a)-1;
 while n>0 do
  dec(n);
  b:=bit_test(a,n);
  if b=0 then
   al:=bit_shift(al,1);
   r:=bit_shift(r,2);
  else
   r:=1+bit_shift(r+al,2);
   al:=1+bit_shift(al,1);
  end;
 end;
 return r;
end.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение29.05.2019, 22:46 


03/10/06
826
Ещё раз взглянув на формулу вначале, на которой основан метод Карацубы, возник вопрос: почему там используются суммы, а не разности? Можно же через произведение разностей записать ту формулу.
yk2ru в сообщении #1394590 писал(а):
$$A=A_{1}+2^{k}A_{2},\quad B=B_{1}+2^{k}B_{2}$$$$AB=A_{1}B_{1}+2^{k}{\Big (}A_{1}B_{1}+A_{2}B_{2}-(A_{1}-A_{2})(B_{1}-B_{2}){\Big )}+2^{2k}A_{2}B_{2}$$
Перемножаются теперь чуть меньшие числа, разности вместо сумм. Переписал код:
код: [ скачать ] [ спрятать ]
Используется синтаксис Pascal
function kd(a:integer; b:integer):integer;#karatsuba method (differences)
var l1,l2,r,d,d2,al,ar,bl,br:integer;
begin
 l1:=bit_length(a);
 if l1<2 then return a*b; end;
 l2:=bit_length(b);
 if l2<2 then return a*b; end;
 d:=max(l1,l2);
 d2:=bit_shift(d,-1);
 al:=bit_shift(a,-d2);
 ar:=a-bit_shift(al,d2);
 bl:=bit_shift(b,-d2);
 br:=b-bit_shift(bl,d2);
 l1:=km(al, bl);
 l2:=km(ar, br);
 r:=km(ar-al, br-bl);
 r := bit_shift(l1+l2-r,d2)+bit_shift(l1,bit_shift(d2,1))+l2;
 return r;
end.

Примеры с квадратами чисел.
Код:
t := timer();
for n:=1 to 1000000 do
s:=kd(n,n);
end;
writeln(timer()-t).
191593
-: 1

==> t := timer();
for n:=1 to 1000000 do
s:=km(n,n);
end;
writeln(timer()-t).
224869
-: 1

==> (224869-191593)/224869*100.
-: 14.7979490

==> 224869/191593.
-: 1.17368067
С разностями отрабатывается быстрее на 15-17 процентов.

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение30.05.2019, 01:19 


16/04/19
161
беззнаковые сложнее вычитать

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение30.05.2019, 10:35 


03/10/06
826
Юрий Матиясевич дает объяснение метода именно через произведение разностей.
Быстрая арифметика ( http://book.etudes.ru/toc/fast-arithmetic/ )

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение30.05.2019, 11:24 
Заслуженный участник
Аватара пользователя


30/01/06
72407
feedinglight в сообщении #1396495 писал(а):
беззнаковые сложнее вычитать

Да вроде нет, с чего бы?

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение30.05.2019, 19:52 


16/04/19
161
Munin
Если $A_{1} - A_{2} < 0$, то плохо же будет, не? Ну или делать так чтобы минусов не было тогда, но это тяжеловасто было бы.

(Оффтоп)

честно говоря вообще не понимаю о чём эта тема

 Профиль  
                  
 
 Re: Возведение в квадрат в компьютерах.
Сообщение30.05.2019, 20:31 
Заслуженный участник
Аватара пользователя


30/01/06
72407
Ну получится число в дополнительном коде. Потом оно просто сработает как отрицательное. (Да, вы правы, тут нужна бо́льшая аккуратность и внимательность.)

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 62 ]  На страницу 1, 2, 3, 4, 5  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group