![]() |
| ||
|
|
Новости |
Поиск |
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;
....
Похоже ли это на работу динамического массива и какова будет разница в скорости??
Defunct (2005-05-27 19:08:00) [61]Verg © (27.05.05 18:52) [17]
Допускается же умножение индексного регистра при адресации массивов. пример:
mov EAX, [EBX + ESI*8]
begin...end (2005-05-27 19:06:00) [62]> alertus © (27.05.05 19:03) [19]
> а что, если используются близкие адреса, то это будет быстрее??
Дело не столько в близких адресах, сколько в облегчении вычисления индексов. И об этом я уже говорил Вам в предыдущей ветке.
var
a: Pointer;
p: ^Real;
begin
GetMem(a, 100 * sizeof(Real));
p := a;
p^ := 0.347;
Inc(p);
p^ := 0.764;
Inc(p);
p^ := 0.764;
...
end.
alertus (2005-05-27 19:03:00) [63]
> а если да, то дин.структуры нафих не нужны - один раз распределил
> память и заполняй ее сколь угоднго "эффективно", хоть на
> асме, хоть на хрясме)
Размеры матриц изначально не известны на первой, ни второй, ни ризультата, но в ходе программы они не меняются.
> Она (вторая функция) - реализована неверно.
Да, я теперь заметил, торопился когда писал.
> Кроме того, с точки зрения оптимизации работы с памятью
> может быть эффективно предварительно транспонировать одну
> из матриц.
Вообще если говорить о моей программе, то у меня вторая матрица - это транспонированная первая (это аппроксимация алгоритма Ньютона для нахождения производной функции нескольких переменных от по двум переменным), а что, если используются близкие адреса, то это будет быстрее??
Всем огромное спасибо, попробую совместить все советы.
-=XP=- (2005-05-27 18:55:00) [64]А причём тут SizeOf(pointer)?
Типа опечатка. Там дальше написано: SizeOf(real)
:)
Verg (2005-05-27 18:52:00) [65]
> Она длится 2.7 секунды, уже лучше чем 4,
Это логично. Она (вторая функция) - реализована неверно. Экономия времени достигнута отсутствием требуемого умножения смещения от указателя на sizeof(real). Реально вычисляются адреса ячеек, как будь-то они размером 1 (байт).
А вообще задумайся - обход столбца одной матрицы и строки другой делаются строго последовательно. Т.о. если уж так хочется оптимизировать, то надо от прямого индексирования, сопровождающегося "в лоб" вычислением адреса через i,j и умножением на sizeof(real) на каждом шаге, переходить на суммирование индексных смещений (наращивание на каждом шаге). Т.о. ты избавишься от операций умножения для вычислений физического адреса ячейки матрицы.
begin...end (2005-05-27 18:50:00) [66]> -=XP=- © (27.05.05 17:45) [2]
> Лучше использовать не +0, +8, а +SizeOf(pointer) * ItemIndex
А причём тут SizeOf(pointer)?
MBo (2005-05-27 18:41:00) [67]Кроме канонического алгоритма вычисления произведения матриц, существуют и более сложные - Винограда, Штрассена. На порядок они выигрыша не дадут, а в пару раз при твоих размерах - возможно. Кроме того, с точки зрения оптимизации работы с памятью может быть эффективно предварительно транспонировать одну из матриц, чтобы обращение к памяти шло подряд, а не скачками. И еще - использование SSE-иструкций современных процессоров - при программировании на ASM или использовании соответствующих компиляторов - може привести к ускорению еще в несколько раз.
Digitman (2005-05-27 18:23:00) [68]
> хочу написать свою функцию на Dephi
это похвально.
и перевешивает любые иные аргументы.
размер матрицы-результата тебе известен ?
думаю - да.
а если да, то дин.структуры нафих не нужны - один раз распределил память и заполняй ее сколь угоднго "эффективно", хоть на асме, хоть на хрясме)
alertus (2005-05-27 18:18:00) [69]
> Какой процессор?
Дома Athlon 1000, а на работе, где я сейчас - Athlon 800.
alertus (2005-05-27 18:17:00) [70]
> В новых версиях Mаtlab'а появился встроенный компилятор,
> но он позволяет (если не ошибаюсь) компилить matlab'овские
> функции в только dll.
Да, это так, но, как я понимаю, если я напишу на матлабе функцию перемножения матриц и сделаю dll, то этой dll нужна другая, где реализовано само умножения, я с трудом понимаю где ее искать, и я не знаю точно как передавать параметры.
Ну и, в конце концов, я хочу написать свою функцию на Dephi.
> Дело в том, что в MatLab'е интерпретатор и у меня Matlab
> работает медленнее, чем тот же код переписанный на Delphi,
> причём в разы.
Да, это абсолютно так для циклов и программ, но если взять отдельно функцию перемножения матриц, то ситуация резко меняется в противоположную сторону.
MBo (2005-05-27 18:16:00) [71]Какой процессор?
alertus (2005-05-27 18:12:00) [72]А что насчет менеджера памяти, я так понимаю, есть такой тип TMemoryManeger, он создается вместе с приложением (TApplication).
Он управляет всей памятью, которая требуется приложению, в том числе и динамическими массивами, но он проверяет не превышены ли текущие границы динамического массива и т.п.
Это, как я понимаю и есть управляющая структура, а я хочу ее обойти или поменьше использовать.
Я совсем не уверен что это все правильно, но я ищу способы ускорить мою программу.
> Скорее всего, у Вас алгоритм другой, нежели в MathLab.
Я думаю, что для перемножения матриц другого алгоритма просто не существует в природе (возможно я не прав). Я использую такой:
var
m1:array[1..2,1..3] of real;
m2:array[1..3,1..2] of real;
mr:array[1..2,1..2] of real;
temp:real;
begin
for i:=1 to 2 do begin
for j:=1 to 2 do begin
temp:=0;
for k:=1 to 3 do begin
temp:=temp+m1[i,k]*m2[k,j];
end;
mr[i,j]:=temp;
end;
end;
end;
Я реализовал свою небольшую прогараммку:
procedure TForm1.Button1Click(Sender: TObject);
var
i,j,k:integer;
temp:real;
t1,t2:real;
pt:^real;
off:integer;
begin
m1.w:=400;
m1.h:=800;
getmem(m1.pint,400*800*sizeof(real));
m2.w:=800;
m2.h:=400;
getmem(m2.pint,800*400*sizeof(real));
mr.w:=400;
mr.h:=400;
getmem(mr.pint,400*400*sizeof(real));
for i:=1 to 400 do begin
for j:=1 to 400 do begin
temp:=0;
for k:=1 to 800 do begin
pt:=pointer(integer(m1.pint)+(i-1+(k-1)*m1.w));
t1:=pt^;
pt:=pointer(integer(m2.pint)+(k-1+(i-1)*m1.h));
t2:=pt^;
temp:=temp+t1*t2;
end;
pt:=pointer(integer(mr.pint)+(i-1+(j-1)*m1.h));
pt^:=temp;
end;
end;
end;
Она длится 2.7 секунды, уже лучше чем 4, да и размер матриц больше, только это не объективно, потому что я на другом компьютере, хотя процессоры почти одинаковые.
Lin7 (2005-05-27 18:11:00) [73]
> alertus © (27.05.05 17:47) [3]
> Я столкнулся с программированием на Matlab, там перемножение
> двух матриц 300x700 элементов real занимает около 1/4 секунды,
> а у меня на Delphi с использованием динамических массивов
> - 4 сек.
Может приведёшь свой код? Дело в том, что в MatLab'е интерпретатор и у меня Matlab работает медленнее, чем тот же код переписанный на Delphi, причём в разы. В новых версиях Mаtlab'а появился встроенный компилятор, но он позволяет (если не ошибаюсь) компилить matlab'овские функции в только dll.
Digitman (2005-05-27 17:58:00) [74]
> Меня беспокоит то, что любая управляющая структура уменьшает
> скорость
при обращении по чтению - ровно на одну-две маш.инструкции.
мизер.
> специально делаю все на наиболее низком уровне
начинать нужно со своего менеджера памяти (адаптированного под конкр.задачи), а не с динамических структур, иначе все твои усилия будут сведены на нет
> хочу попробовать на asm'е это сделать
попробуй.
тем более что садомазо нынче в моде)
-=XP=- (2005-05-27 17:54:00) [75]Тут проблема не с динамическими массивами.
Скорее всего, у Вас алгоритм другой, нежели в MathLab.
alertus (2005-05-27 17:52:00) [76]
> любой дин.тип данных предусматривает упр.структуру ... она
> у тебя ГДЕ ?
Меня беспокоит то, что любая управляющая структура уменьшает скорость, я специально делаю все на наиболее низком уровне, хочу попробовать на asm'е это сделать...
alertus (2005-05-27 17:50:00) [77]
> Лучше использовать не +0, +8, а +SizeOf(real) * ItemIndex
Да, я так и хотел сделать в дальнейшем.
А как насчет скорости или другой реализации??
Digitman (2005-05-27 17:50:00) [78]
> Почему не похоже
по кочану.
любой дин.тип данных предусматривает упр.структуру ... она у тебя ГДЕ ?
alertus (2005-05-27 17:47:00) [79]Почему не похоже, ведь у меня получился массив из 100 элементов типа real, к каждому из которых я имею доступ.
И если я изначально не знаю размер массива, то я могу его задать в ходе выполнения программы (после мне его менятьт не потребуется).
Я столкнулся с программированием на Matlab, там перемножение двух матриц 300x700 элементов real занимает около 1/4 секунды, а у меня на Delphi с использованием динамических массивов - 4 сек.
Matlab написан на C++, там динамические массивы объявляются так:
float *a.
В общем я хочу ускорить операции с динамическими массивами, судя по Matlab'у это возможно.
Может быть кто-нибудь знает как это запрограммировано на Matlab'е??
-=XP=- (2005-05-27 17:45:00) [80]Похоже. Но и только.
Лучше использовать не +0, +8, а +SizeOf(pointer) * ItemIndex
А зачем так изголяться? Чем динамические массивы не подошли?
Или конструкция типа:
{$RANGECHECKS OFF}
type
PRealArray = ^TRealArray;
TRealArray = array[0..0] of real;
var
A: PRealArray;
begin
GetMem(A, 100 * SizeOf(real));
A^[2] := 0.764;
...