Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > multi-mul


Автор: setnull 26.1.2012, 11:50
Все здравствуйте!

Подскажите, кто знает, существует ли возможность произвести опреацию, к примеру, для двух int32, яваляющуюся попарным произведение четырех их байт, одним махом, не разбивая на байты, с результатом получается int64?


Спасибо!!!

Автор: _Y_ 26.1.2012, 12:37
Так это, надо понимать, от языка зависит. В каком-то, наверное, можно.

Сам я на C++ никогда не писал, но, вроде, там можно переопределять арифметические операторы. Вот переопределить и дальше считать одним махом.

Автор: setnull 26.1.2012, 12:59
Речь пока идет без привязки к конкретному языку.
Исходя из того, что есть операции низкого уровня над 4b целым (сдвиги, сложения, умножения, побитовые) возможно ли реализовать алгоритм быстрого умножения его четырех байтов отдельно?
Организовать конечно можно пошаговые сложения, слежения за переполнениями и.тд. Интересует существование именно быстрого алгоритма, выигрывающего в производительности за счет сведения четырех операций в один поток. Или такое в принципе невозможно\неоправданно?

Спасибо!

Автор: Pavia 26.1.2012, 18:44
setnull, 
Как, бы вам с вопросом надо определиться. Что вы хотите?

Цитата

Исходя из того, что есть операции низкого уровня над 4b целым (сдвиги, сложения, умножения, побитовые) возможно ли реализовать алгоритм быстрого умножения его четырех байтов отдельно?

Как-то у вас русский язык хромает. ДА и мысль осталась не ясна.

Советую посмотреть лекцию.
http://www.intuit.ru/department/supercomputing/baseraspp/

И это посмотри.
 http://ru.wikipedia.org/wiki/Классификация по Флинну

Цитата

яваляющуюся попарным произведение четырех их байт, одним махом, не разбивая на байты, с результатом получается int64?
 На ПЛИС можно, используя модульную арифметику. 

Цитата

 за счет сведения четырех операций в один поток. Или такое в принципе невозможно\неоправданно?
 Возможно.  Если использовать процессор с VLIW. По поводу оправданности, я бы сказал вопрос открытый.

Автор: setnull 26.1.2012, 21:13
Лекция заинтересовала (вступление), обязательно вернусь к ней!!!
Про классификацию не совсем понял, в каком ребре соприкосновение с задачей...

Изложил задачу таки не совсем ясно...

Программирование последовательное (пока что smile
Возможно ли реализовать с помощью целочисленных операций над двумя целыми числами длинной в 4б, попарное умножение их байтов поотдельности.

например

а      = 0х01020304
б      = 0х00020201

результат операции
а # б= 0х00040604 (или пускай с поправкой на размерность 0х00000004000060004)

но при этом чтоб алгоритм заключался не в том, чтоб с максой 0хff обращаться к каждому байту, и разложить на 4 операции умножения, а именно производя операции над единым целым в 4б. 


Автор: Pavia 27.1.2012, 14:17
пример 1.
Код


type
 T4Byte=array [0..3] of Byte;
 T2Word=array [0..1] of Word;
var
 a, b, c: DWord;
begin
a:=$01020304;
T2Word(b)[0]:=T4byte(a)[0]*T4byte(a)[1];
T2Word(b)[1]:=T4byte(a)[2]*T4byte(a)[3];
c:=T2Word(b)[0]*T2Word(b)[1];
Write(c);
end.


Пример 2.
Тоже самое только дугая запись. В с/с++ можно сделаь аналогично через struct union.

Код

type
 TRecDWord=record
             case integer of
             0: b0, b1, b2, b3:Byte;
             1: w0, w1: Word;
             2: d0: DWord;
             end;
           end;
var
 a, b, c: TRecDWord;
begin
a.d0:=$01020304;
b.w0:=a.b0*a.b1;
b.w0:=a.b0*a.b1;
c.d0:=b.w0*b.w1;
Write(c);
end.


пример 3
Код

type
 TRecDWord=record
             case integer of
             0: b0, b1, b2, b3:Byte;
             1: w0, w1: Word;
             2: d0: DWord;
             end;
           end;
var
 a, b, c: TRecDWord;
begin
a.d0:=a.b0*a.b1*a.b2*a.b3; 
Write(c);
end.


В третьем примере, код будет работать 3 цикла умножения. А во втором и первом примерах 1 и 2 умножения не имеют зависимости поэтому они могут выполниться параллельно.
Поэтому скорость первого и вторго примера 2 цикла умножения.
В третьем примере компилятор может распараллелить, но на практике думается делать он это не будет.
Параллельность зависит от процессора что-то можно распараллелить что-то нельзя.

Вполне возможно что в процессорах с VLMW или RISC процессорах можно записать 3 умножения одной командой.
На x86 точно нет такой команды, только в 2 команды. Сначала за раз 2 умножения потом еще одно.
Даже Intel и Microsoft специально добавили в сови компиляторы С/с++ наборы instrics которые реализуют низкоуровневые SIMD команды CPU в виде высокоуровневых функций.

SIMD - расшифровывается как, ода инструкция много данных. 
За частую при таком подходе данные обрабатываться параллельно, за счёт этого имеем прирост в производительности.

А ещё процессоры интел называют мульти скалярными. Это архитектура MIMD(мноо инструкций много данных)  
Процессор может выполнять команды которые не имеют зависимости по данным параллельно.
Так что второй и первый пример хотя и имеют 3 умножени, но будут выполняться по скорости как 2 последовательных умножения.

Зачем нужен SIMD когда есть MIMD? На SIMD обычно пишет челове программист и он способен распаролелить код лучше чем это сделает компилятор+процесор.
SIMD выступает в роли помощника, подсказывая процессору над какими данными можно вести код паролельно. 
В процессор трудно вставить крутой алгоритм анлиза, который бы паролелил днные поэтому он не такой умный.

К SIMD относятся процессоры с наборами команд MMX,SSE, SSE2 и тд. 
GPU обычно тоже выполняют одну команду над 4 компонентами цвета одного пикселя и над 4 пикселями.
В некоторых ARM(практически во всех) тоже есть свои наборы команд Neon.
И в других процессорах тоже есть свои инструкции.

Прирост скорости достигается за счёт параллельности. А вот способы для достижения параллельности бывают разные.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)