![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Pointer->Integer->Pointer
alertus © (2005-05-27 17:36:00)Подскажите, пожалуйста, если я пишу так:
a:^real;
p:^real;
....
getmem(a,100*sizeof(real));
p:=pointer(integer(a)+0);
p^:=0.347;
p:=pointer(integer(a)+8);
p^:=0.764;
p:=pointer(integer(a)+16);
p^:=0.764;
....
Похоже ли это на работу динамического массива и какова будет разница в скорости??
begin...end (2005-05-30 20:39:00) [1]> alertus © (27.05.05 21:02) [33]
Дополнение к [78]: матрицы должны быть расположены в памяти по строкам -- вначале первая строка, затем вторая и т.д. Матрица результата будет размещена таким же образом.
Defunct (2005-05-30 20:08:00) [2]> begin...end
Прошу прощения что поставил неверный коментарий:
{ подготовка MMX и SSE2 }
Defunct (2005-05-30 20:07:00) [3]begin...end © (30.05.05 20:05) [78]
Код под P4, mulsd на P3 нет.
begin...end (2005-05-30 20:05:00) [4]> alertus © (27.05.05 21:02) [33]
Этот код не выполняет умножения матриц. Вот рабочий код:
const
M = 311; // Число строк в A и столбцов в B
N = 700; // Число строк в B и столбцов в A
type
TElement = Real;
PElement = ^TElement;
var
Temp: TElement;
i, j, k: Integer;
A, B, C: PElement;
pA, pB, pC: PElement;
begin
GetMem(A, M * N * sizeof(TElement));
GetMem(B, N * M * sizeof(TElement));
GetMem(C, M * M * sizeof(TElement));
try
pC := C;
for i := 1 to M do
begin
pA := PElement(Integer(A) + (i - 1) * N * sizeof(TElement));
for j := 1 to M do
begin
pB := PElement(Integer(B) + (j - 1) * sizeof(TElement));
Temp := 0;
for k := 1 to N do
begin
Temp := Temp + pA^ * pB^;
Inc(pA);
Inc(pB, M)
end;
pC^ := Temp;
Inc(pC);
Dec(pA, N)
end
end
finally
FreeMem(A);
FreeMem(B);
FreeMem(C)
end
end.
> Defunct © (29.05.05 07:54) [69]
> Defunct © (29.05.05 08:31) [70]
Нерабочий код. Вылетает с External Exception.
DiamondShark (2005-05-30 17:53:00) [5]
> зависит ли скорость от расстояния между этими физическими
> адресами??
В системах с многоуровневой памятью -- зависит.
Иногда очень сильно.
Defunct (2005-05-30 17:28:00) [6]alertus © (30.05.05 17:06) [74]
Боюсь у Athlon'a нет SSE. (во всяком случае насколько я помню у Athlon TB не было, а вы говорили что у вас Athlon 800, это скорее всего и есть TB). У AMD процессоров есть 3DNow! для работы с числами с плавающей точкой, так что ищите мануал на сайте AMD а не Intel'а. Вам всего навсего нужна замена команд ADDPD/ADDSD и MULPD/MULSD.
Digitman (2005-05-30 17:11:00) [7]на сайте у Анатолия Подгорецкого, кажется, был ..
в оригинале файл называется 24547112.pdf
IA-32 Intel ® Architecture
Software Developer’s
Manual
Volume 2 :
Instruction Set Reference
alertus (2005-05-30 17:06:00) [8]Как я понял, там почти тоже самое, как программирование на асме, только добавляются регистры новые для быстрых операций с вещественными числами??
А ссылку не подскажете??
Digitman (2005-05-30 17:03:00) [9]
> Подскажите, пожелуйста, где можно прочитать про инструкции
> SSE??
в мануалах от Интела ... это же его детище ..
alertus (2005-05-30 17:00:00) [10]Подскажите, пожелуйста, где можно прочитать про инструкции SSE??
Marser (2005-05-29 11:03:00) [11]
> begin...end ©
> Defunct ©
Break!
Вы уже давно грызётесь. А толку-то? Никому из вас это на пользу не идёт, авторитету не добавляет. Только однеому создаёт неповторимый оттенок, а другому ещё более его усугубляет.
Зачем?
Defunct (2005-05-29 08:31:00) [12]Кстати именно этот множитель индекса и не учтен в [33] его вообще там нет, соответственно функция [33] не рабочая .. и моя не рабочая (т.к. делал по образу [33]), а чтобы сделать ее рабочей надо поменять в цикле k этот код
movd eax, mm0 ; // pointer to B
add eax, ebx ;
movd esi, mm4
movq xmm0, [eax + esi*8]
movd eax, mm1 ; // pointer to A
add eax, ebx
movd esi, mm3
на такой:
movd eax, mm0 ; // pointer to B
movd esi, mm4
add esi, ebx ;
movq xmm0, [eax + esi*8]
movd eax, mm1 ; // pointer to A
movd esi, mm3
add esi, ebx
Defunct (2005-05-29 07:54:00) [13]TUser © (29.05.05 05:01) [68]
навеяно вашими размышлениями..
Алгоритм [33] на асме с MMX и SSE и масштабированием индексов о котором здесь был спор с begin...end.
Работает почти в 3 раза быстрее чем [33]. 0.38 сек. (моя функция) против 1.0сек. (оригинал [33])
procedure TForm2.Button4Click(Sender: TObject);
var
a:^real; //311x700
b:^real; //700x311
c:^real; //311x311
begin
getmem(a,311*700*sizeof(real));
getmem(b,311*700*sizeof(real));
getmem(c,311*311*sizeof(real));
memo1.lines.add(writems);
{}
asm
{ подготовка MMX и SSE }
push ebx
push esi
mov eax, c
movd mm6, eax
mov eax, b
movd mm0, eax
mov eax, a
movd mm1, eax // A - low dword
mov eax, 311
movd mm2, eax
punpckldq mm2, mm2 // Двойной множитель на 311
// for i := 0 to 310 do
mov ecx, 310
@L1:
// for j := 0 to 310 do
mov edx, 310
@L2:
pxor xmm1, xmm1 // Переменная Temp в фантазии SSE
// Расчет i/j адреса вынесен из цикла k
movd mm4, ecx
punpckldq mm4, mm4
movd mm4, edx
movq mm3, mm4
pmullw mm3, mm2
pmulhw mm4, mm2
pslld mm4, 16 // j * 311
paddd mm4, mm3
punpckldq mm3, mm4 // i * 311
// for k := 0 to 699 do
mov ebx, 699
@L3:
movd eax, mm0 ; // pointer to B
add eax, ebx ;
movd esi, mm4
movq xmm0, [eax + esi*8]
movd eax, mm1 ; // pointer to A
add eax, ebx
movd esi, mm3
mulsd xmm0, [eax + esi*8]
addpd xmm1, xmm0 ; // temp:=temp+pa^*pb^;
dec ebx
jns @L3
movd eax, mm6 ; // pointer to C
movd esi, mm4 ; // j * 311
add esi, ecx ; // + i
movq [eax + esi*8], xmm1 // сохраняем temp
dec edx
jns @L2
dec ecx
jns @L1
emms
pop esi
pop ebx
end;
memo1.lines.add(writems);
end;
TUser (2005-05-29 05:01:00) [14]> Если на асме есть возможность расчитать индекс быстрее,
почему бы не воспользоваться этим?
Да я не против. Просто быстрее в таком случае означает - процентов на 10 максимум, я понимаю. Обычно, если уж программа медленно работает, то очень сильно помогает изменение логики работы алгоритма, а не переход на си, ассемблер или покупка супер-компьютера. А судя по [10] тут как раз такой случай, что алгоритм можно улучшить.
Хотя против асма тоже ничего не имею.
Defunct (2005-05-28 21:01:00) [15]begin...end © (28.05.05 20:31) [66]
> Если это так, то [31] и [36] можно объяснить только корявостью написанного Вами теста.
Странно, почему же у меня "коряво написанный тест" это подтверждает.
А может быть ваше "неламерское" видоизменение, так повлияло. Не вы ли написали:
> Ваш код я видоизменил: вместо ламерского способа измерения времени
> Верно, Вы больше похожи на дошкольника.
>> выслушивать все это дерьмо
> Придётся.
LMD
begin...end (2005-05-28 20:31:00) [16]> Defunct © (28.05.05 18:59) [65]
> LMD
Из этой реплики следует, что Вам надоело жить.
>> Судя по тому, как Вы были уверены в результате,
> Я до сих пор в нем уверен.
А я до сих пор уверен в результатах [31] и [36].
> Defunct © (28.05.05 18:59) [65]
Если это так, то [31] и [36] можно объяснить только корявостью написанного Вами теста.
> я тебе не школьник
Верно, Вы больше похожи на дошкольника.
> выслушивать все это дерьмо
Придётся.
Продолжать разговаривать с деревом смысла не вижу.
Defunct (2005-05-28 18:59:00) [17]Прочитать о масштабировании индексных региcтров можно в "Instruction Set Reference Vol 2.A" в разделе 2.6 "Addressing-Mode Enconiding of ModR/M and SIB"
В "Vol 2.B, Appendix B" можно найти что инструкции
[ecx]
[ecx*8]
выполняются за одинаковое количество тактов.
Всего хорошего.
PS: (как меня уже дастали выбрыки begin...end, я тебе не школьник, чтобы от тебя выслушивать все это дерьмо).
Defunct (2005-05-28 18:03:00) [18]begin...end © (28.05.05 10:55) [61]
LMD
> Судя по тому, как Вы были уверены в результате,
Я до сих пор в нем уверен.
Sergey Masloff (28.05.05 11:28) [62]
прочитайте ветку дальше.
TUser © (28.05.05 13:11) [63]
Если на асме есть возможность расчитать индекс быстрее, почему бы не воспользоваться этим?
TUser (2005-05-28 13:11:00) [19]Вообще, не думаю, что тут надо браться за асм или изменять логику работы с дин.массивами. Сущействует несколько алгоритмов умножения матриц, который различаются скоростью работы. Посмотрите в интернете по словам 'алгоритм Штрассена' - это один из самых быстрых.
Sergey Masloff (2005-05-28 11:28:00) [20]begin...end © (27.05.05 20:58) [31]
>способа измерения времени выполнения кода функцией использовал >GetTickCount, хотя это тоже не лучший способ.
Ну да. Это ж время работы системы а не вашего кода. Так что GetThreadTimes() было бы уместнее (если конечно это в NT системе происходит). А иначе меряется средняя по больнице температура.