Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2006.01.29;
Скачать: [xml.tar.bz2];

Вниз

Matrix Reloading Alpha :)   Найти похожие ветки 

 
Loginov Dmitry ©   (2006-01-03 14:54) [0]

На самом деле это все тот же матрикс. Проснулся 1-го января, и сразу осенила мысля: а не переделать ли все это нахрен. Парился двое суток. Убрал из ядра все лишнее, переделал практически все функции, немножко уменьшил основной модуль (всего на 1000 строчек). Вообщем, в ядре оставил только самые необходимые функции.
Насчет функциональности... По-прежнему поддерживаются только 2-мерные массивы с элементами типа Real (aka Double). Все операции стали работать значительно быстрее, чем в первой версии (она демонстрировалась в начале сентября). Сравнивать по скорости с матлабом не стал, но, думаю, практически все операции должны работать быстрее, чем аналоги матлаба.
Подумал (время было :) над значимостью разработки. Оказывается матрикс - средство не универсальное, а специализированное, и годится оно только для работы с двухмерными массивами вещественных чисел (многомерные массивы до сих пор не поддерживаются, ввиду их практической
ненужности. В матлабе они есть, но ими пользуются исключительно
математики-любители-поизвращаться :).
В новой версии особое внимание было отведено взаимодействию рабочих областей. Теперь все временные рабочие области зависят от родительских рабочих областей и уничтожаются автоматически при удалении родительской рабочей области. (В визуальных компонентах реализован похожий механизм).
Вообщем, вы можете скачать этот шедевд извращенной :) мысли по адресу:
http://matrix.kladovka.net.ru/matrix_reloading.zip

Сейчас мне интересно, возникнут ли у кого-нибудь претензии по качеству оформления кода, ес-но по актуальности данной разработки, по скорости работы каких-либо операций. Может ли ядро матрикса быть включено в новые версии Delphi (если нет, что что для этого нужно сделать или с кем
связаться по этому поводу)?

Любая критика приветствуется и будет восприниматься адекватно.


 
Gero ©   (2006-01-03 15:02) [1]

А что это?


 
ПЛОВ ©   (2006-01-03 15:03) [2]

И чего с ним делать то, с этим файлом? :)


 
Loginov Dmitry ©   (2006-01-03 16:13) [3]


> И чего с ним делать то, с этим файлом? :)


Для начала необходимо закачать архив, а потом распаковать его в любую директорию на жестком диске. Там находится тестовый проект MatTest.dpr, так вот его нужно окрыть с помощью интегрированной среды разработки Borland Delphi N, и откомпилировать его. В результате будет создано приложение MatTest.exe. Его можно запустить и посмотреть, как там все круто работает. Но самое главное не приложение, а файлик Matrix.pas. Он может быть использован автономно, и его даже можно подключить к любому приложению, разрабатываемому в Delphi.

Как, хорошо ответил?
:)


 
ПЛОВ ©   (2006-01-03 16:34) [4]

Так как оно работает??? Для чего прога нужна вообще?


 
Loginov Dmitry ©   (2006-01-03 17:05) [5]


> ПЛОВ ©   (03.01.06 16:34) [4]
>
> Так как оно работает??? Для чего прога нужна вообще?


Рекомендую посетить сайт разработки:
http://matrix.kladovka.net.ru

Там куча текста, но надеюсь после прочтения станет ясно как это все работает.

Для чего нужна... Матрикс - замена двухмерных вещественных массивов. Если вы такие массивы не используете, то пользы от матрикса вам не видать. Так что лозунг: "Товарищи программисты! Используйте двухмерные вещественные массивы в своих проектах и вы узнаете что такое счастье" :о)


 
Плохиш ©   (2006-01-03 17:12) [6]


> Loginov Dmitry ©   (03.01.06 16:13) [3]

Напоминает албанский вирус. Вторая версия?


 
ПЛОВ ©   (2006-01-03 17:23) [7]


> Напоминает албанский вирус. Вторая версия?

Если вы не используете в своих проектах албанских вирусов, то программа вам мало чем поможет :)


 
Loginov Dmitry ©   (2006-01-03 17:37) [8]


> Напоминает албанский вирус. Вторая версия?


Ага! Он самый :)

Вопрос исчерпан:

> ПЛОВ ©   (03.01.06 16:34) [4]

или как?


 
Gero ©   (2006-01-03 17:38) [9]

> Матрикс - замена двухмерных вещественных массивов

А чем не устраивают собственно двухмерные вещественные массивы?


 
ferr ©   (2006-01-03 18:37) [10]

Скачать:

Всю систему полностью, 80 кбайт, дата обновления: 11.11.2005;
Только справочную систему, 300 кбайт, дата обновления: 11.11.2005;


 
Loginov Dmitry ©   (2006-01-03 18:41) [11]


> А чем не устраивают собственно двухмерные вещественные массивы?


Если речь идет об обычных массивах (A: array[1..10, 1..10] of Double), то не устраивает некая их статичность. А в динамических массивах (array of array of Double) устраивает в принцине все. Но вот существуют задачи, в которых ни статичные, ни динамичные массивы применять попросту неудобно. Именно эта неудобность и послужила толчком к созданию менеджера массивов МатрикС.
Хотя можно перечислить неудобства и динамических массивов:

1) необходимость объявления.
Когда в вашей программе куча всяких массивов, она не смотрится особенно красивой (это в отношении кода). А если вы используете подпрограммы для обработки массивов, в которые передаются динамические массивы, возвращаются динамические массивы и всюду одно и то же: array of array of ...
Я занимаюсь достаточно сложным проектом - компьютерной диагностической системой. Она анализирует снятые сигналы ЭКГ. ЭКГ довольно сложно обрабатывать, и многие операции очень сложно организовать (автоматическое определение кардиоциклов, выделение зубцов и интервалов, погашение трендов, обработка с помощью нейронных сетей и масса других функций), и при этом код становится очень трудночитаемым, а вследствие этого его очень трудно редактировать

2) необходимость своевременного освобождения памяти.
Если вы выделили память с помощью SetLength(), то вы должны заботится об ее освобождении, особенно, если динамический массив объявлен и используется в подпрограмме. Вот если в подпрограмме объявлено множество динамических массивов, то запросто можно забыть освободить память для любого из них

3) индексация в динамических массивах начинается с нуля
Это далеко не всегда удобно

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

5) возможны глюки при использовании динамических массивов
Пару раз наблюдал такое явление, как ошибка модификации заданного элемента (но здесь конечно все дело в звездах)

Статичные массивы работают побыстрее, благо вся служебная информация уже доподлинно известна, однако использование статичных массивов, объявленных в процедурах чревато неприятными последствиями: медленный доступ (да, работа с локальным массивом выполняется дольше, чем с глобальным), ограниченность стека (может произойти переполнение)

А глобальные статичные массивы тоже не всегда удобны. Допустим, вы объявили большой глобальный массив, который используется только на определенном этапе работы программы, а память он будет жрать всю дорогу. В этом случае лучше использовать динамический массив со всеми его минусами.

Я со всей ответственностью заявляю, что Матрикс избавлен от всех перечисленных недостатков.


 
Loginov Dmitry ©   (2006-01-03 18:49) [12]


> ferr ©   (03.01.06 18:37) [10]
>
> Скачать:
>
> Всю систему полностью, 80 кбайт, дата обновления: 11.11.
> 2005;
> Только справочную систему, 300 кбайт, дата обновления: 11.
> 11.2005;


Ну справочную систему можно скачать почитать что там, но она пока только для старой версии. В новой версии многие функции переименованы, переделаны, но основные представления о системе получить можно.
Старая версия от 11.11.2005 пока останется. Дело в том, что есть в кладовке несколько проектов, которые ссылаются на нее. Брр... она сама находится в кладовке.
Таким образом, о новой версии знают пока только жители Потрепаловки


 
Loginov Dmitry ©   (2006-01-03 20:44) [13]


> ferr ©   (03.01.06 18:37) [10]


Сайт подправил :). Ссылка теперь есть даже на сайте :)


 
GuAV ©   (2006-01-03 21:01) [14]


> 1) необходимость объявления.

Это не недостаток.

> array of array of ...

Зачем, если все одного типа, можно объявить тип массива.

> Когда в вашей программе куча всяких массивов

Они будут, и будут заданы и использованы, так или иначе.


> 2) необходимость своевременного освобождения памяти.


> Если вы выделили память с помощью SetLength(), то вы
> должны заботится об ее освобождении

При правильно написаном коде — нет, динамические массивы совобождаются сами.


> 3) индексация в динамических массивах начинается с
>нуля
> Это далеко не всегда удобно

Почти всегда. Если очень хочется не с нуля, можно использовать Variantы-массивы.


>4) невысокая скорость обработки элементов массива
> Помимо элементов массива хранится дополнительная
> служебная информация.

И без неё никак, она нужна. Если нужно, чтобы двумерный массив был не массивом из одномерных массивов, т.е. без управляющих структур для "внутренних" массивов, то —  Variantы-массивы, но кому эти упр структуры могут мешать ?


> 5) возможны глюки при использовании динамических
>массивов
> Пару раз наблюдал такое явление, как ошибка
> модификации заданного элемента

>(но здесь конечно все дело в звездах)

В качестве кода. IMO.


> однако использование статичных массивов, объявленных в
> процедурах чревато неприятными последствиями:
> медленный доступ (да, работа с локальным массивом
> выполняется дольше, чем с глобальным)


Это чего ?


 
Loginov Dmitry ©   (2006-01-03 23:04) [15]


> GuAV ©   (03.01.06 21:01) [14]


В посте [11] я описал недостатки обычных массивов, и тутже встретил критику по отношению к моему IMHO (забыл приписать :). Теперь критики, чувствую, будет еще больше :)


> 1) необходимость объявления.

В матриксе нет необходимости объявлять массивы. Все массивы расположены в рабочих областях. Обращение к массиву выполняется по имени (или индексу). Можете создать хоть 100, хоть 1000 массивов с уникальными именами - и никакого объявления (ну приспичило мне 1000 массивов с разными именами создать - что я должен для каждого писать:
Array1: TReal2Array;
Array2: TReal2Array;
........................
Array1000: TReal2Array)

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


> 2) необходимость своевременного освобождения памяти.

> При правильно написаном коде — нет, динамические массивы
> совобождаются сами.

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


> > 3) индексация в динамических массивах начинается с
> >нуля
> > Это далеко не всегда удобно
>
> Почти всегда. Если очень хочется не с нуля, можно использовать
> Variantы-массивы.

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


> >4) невысокая скорость обработки элементов массива
> > Помимо элементов массива хранится дополнительная
> > служебная информация.

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


> Это чего ?

Это факт. Протестируйте следующий код, и все станет ясно:


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;
 //Ar1, Ar2, Ar3: array[1..100, 1..100] of Real;
implementation

{$R *.dfm}

{Матричное умножение: Ar3 = Ar1 * Ar2}
procedure TForm1.Button1Click(Sender: TObject);
var
 i,j, k, c:integer;
 R: Real;
 Tc: cardinal;
 Ar1, Ar2, Ar3: array[1..100, 1..100] of Real;
begin
 for i := 1 to 100 do
   for j := 1 to 100 do
   begin
     Ar1[i,j] := Random;
     Ar2[i,j] := Random;
   end;
 Tc := GetTickCount;
 for c := 1 to 100 do
   for i := 1 to 100 do
     for j := 1 to 100 do
     begin
       R := 0;
       for k := 1 to 100 do
         R := R + Ar1[i,k] * Ar2[k,j];
       Ar3[i,j] := R;
     end;
 showmessage(inttostr(GetTickCount - Tc));
end;

end.


Обработка локальных массивов в данном случае будет выполняться в 1.63 раза дольше, чем обработка глобальных массивов (а это почти в 2 раза).
Пожалуйста, прокомментируйте этот факт?

И еще насчет служебных конструкций... Вам нужно сохранить динамический массив в двоичный файл. Каким образом вы это сделаете?


 
Loginov Dmitry ©   (2006-01-04 09:52) [16]

Мастера! Жду вашей критики :)


 
mirima   (2006-01-04 12:13) [17]

http://www.osl.iu.edu/research/mtl/


 
Loginov Dmitry ©   (2006-01-04 13:49) [18]


> mirima   (04.01.06 12:13) [17]
>
> http://www.osl.iu.edu/research/mtl/


Да... Неплохо...
Был бы у меня собственный университет, я бы тоже че нибудь такое забацал :). Трудился там явно не один человек, а целая команда на протяжении нескольких лет.

На основе матрикса можно ваять не менее замечательные вещи. Существует ядро матрикса - менеджер массивов. В нем заложены все необходимые операции для работы с двухмерными массивами:
- создание массивов
- удаление массивов
- изменение размеров
- добавление или удаление строк (или столбцов)
- вставка строк или столбцов
- копирование участка матрицы
- многое другое.

Также особое внимание уделялось работе с файлами. Массивы можно сохранять в файлы, загружать из файлов.

Матрикс - это что-то вроде миниатюрного матлаба (надеюсь, что только пока :). Ведь все наверное знают что такое Матлаб, работали в нем. Этот язык заточен для работы с 2-мерными массивами (повторюсь, что многомерные массивы в матлабе не используются, их полностью заменили ячейки).

Достоинство Матлаба в чем?
1 - в его низкой цене (для русского пользователя дистрибутив матлаба стоит $3, а лицензия полностью бесплатна :)
2 - в скорости работы. Желаемого результата вы добъетесь гораздо быстрее в Матлабе, чем в  C++ или в Delphi. Даже с MTL для С++ вы наверняка провозитесь дольше, даже просто потому, что синтаксис языка С++ довольно сложный.
3 - в Матлабе исключительно просто программируются пользовательские функции (М-файлы)

Теперь все перечисленные достоинства перенесите в матрикс, и вспомните, что для Delphi никаких аналогов MTL не существует.


 
Kerk ©   (2006-01-04 14:38) [19]

http://matrix.kladovka.net.ru/guest.cgi

В IE, опере и FF цвета совсем разные в гостевухе. В чем дело-то???


 
Zeqfreed ©   (2006-01-04 14:58) [20]

Kerk ©   (04.01.06 14:38) [19]

/gstyles.css:
body
{
 background-color: 00E3E3E3;


00E3E3 — бирюзовый, или какой там. В 16-ричном формате цвета в CSS записываются с префиксом # и 6-ю знаками. Опера интерпретировала этот цвет так, видимо :)


 
Gero ©   (2006-01-04 15:04) [21]

> 00E3E3E3

Что это?


 
raidan ©   (2006-01-04 15:05) [22]

Даже не компилится :)
NNet.pas не найден.


 
Zeqfreed ©   (2006-01-04 15:08) [23]

raidan ©   (04.01.06 15:05) [22]
Закомментируй.


 
Kerk ©   (2006-01-04 15:09) [24]

И правда цвета криво заданы :))
Поправил


 
raidan ©   (2006-01-04 15:14) [25]

Закомментировал и запустил...
Через 1 минуту все стер :)


 
Loginov Dmitry ©   (2006-01-04 15:59) [26]


> raidan ©   (04.01.06 15:05) [22]
>
> Даже не компилится :)
> NNet.pas не найден.


Блин, ну так всегда :( Pas -файлы удаляешь, а про ДСУ-шки забываешь. Теперь все должно компилиться.


> Kerk ©   (04.01.06 15:09) [24]
>
> И правда цвета криво заданы :))
> Поправил


Спасибо! :)


> raidan ©   (04.01.06 15:14) [25]
>
> Закомментировал и запустил...
> Через 1 минуту все стер :)


А что конкретно не понравилось?. Может что лишнее убрать?)))))


 
Loginov Dmitry ©   (2006-01-04 22:35) [27]

Люди!!! Вы где все? :)

Тема только началась, я что один ее развивать должен? :(

Хоть кто-нибудь смотрел исходники, как впечатления?


 
Zeqfreed ©   (2006-01-05 00:40) [28]

Loginov Dmitry ©   (04.01.06 22:35) [27]

> кто-нибудь смотрел исходники, как впечатления?

Жутко не понравилось вот это:

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
var
 Num, I, Cnt: Integer;  
begin
 Num := Node.ImageIndex;

 if Num = 2 then RefreshInfo;

 Cnt := panMain.ControlCount;
 for I := 1 to Cnt do
   begin
     if panMain.Controls[I - 1].Tag <> Num then
       panMain.Controls[I - 1].Visible := False else
     begin
       with panMain.Controls[I - 1] do begin
         Left := 0; Top := 0;
         Align := alClient;
         Visible := True;  
       end;
     end
   end;
 panTestSpeed.Visible := True;
end;


Я имею в виду саму организацию «страниц». Интересно, на сколько удобно разрабатывать дизайн формы при таком подходе?

В самом «Матриксе» не понравилось то, что поиск по именам массивов выполнен «в лоб» — перебором. Думаю, что при заявленной в [15] тысяче массивов и интенсивной работе с оными, «Маткад» по скорости не переплюнуть. Но это, конечно, не особо критично.
Глубже не смотрел.

Так как пользоваться массивами дробных чисел мне приходится не часто, то практического применения библиотеки для себя не могу представить. Но, пробежавшись по спискам ф-ций не нашёл там пересечения и объединения — возможно, кому-то они окажутся полезными.

Вот, в общем-то, мое скормное мнение. Надеюсь ничего, что в несколько негативном ракурсе.


 
Loginov Dmitry ©   (2006-01-05 09:54) [29]


> Я имею в виду саму организацию «страниц». Интересно, на
> сколько удобно разрабатывать дизайн формы при таком подходе?
>


Жутко неудобно. Честно! Но предложите, как еще можно набросать пол-сотни панелей на одну форму, используя только стандартные компоненты Дельфи7.


> В самом «Матриксе» не понравилось то, что поиск по именам
> массивов выполнен «в лоб» — перебором. Думаю, что при заявленной
> в [15] тысяче массивов и интенсивной работе с оными, «Маткад»
> по скорости не переплюнуть. Но это, конечно, не особо критично.
>
> Глубже не смотрел.


Вот как раз по этой причине и была разработана рабочая область. В каждой рабочей области можно хранить сколько угодно массивов. Но сколько вы хотите хранить для практических нужд? 5 массивов? 10 массивов? Но больше - врядли.
Конечно, надо менять алгоритм перебора. Просто я этой теме не уделил должного внимания.
А вот маткад по скорости матрикс переплюнет. Да да да. Ведь на самом деле указанный массив ищеться только один раз. Просто после поиска он сразу индексируется, чтоб в следующий раз не искать.
Только что попробовал в матриксе создать 10000 массивов:


> procedure TForm1.Button82Click(Sender: TObject);
> var
>   I: Integer;
> begin
>   StartCikle;
>   for I := 1 to 10000 do
>     Base.NewZeros("A" + Inttostr(I), 1, 1);
>   EndCikle;   // 18.6 сек
> end;


Создавал долго - почти 20 секунд, однако в при дальнейшей работе такое обилие массивов совершенно не ощущалось. Попробовал создать 10000 массивов в матлабе:


> clear
> for i=1:10000
>   eval(sprintf("A%d=1;",i));
> end;


Создал быстро (примерно за секунду). Однако при дальнейшей работе такое обилие массивов здорово ощущается - матлаб попросту виснет.

Я буду очень признателен, если вы дадите совет, как реализовать наиболее быстрый поиск массивов.


> Так как пользоваться массивами дробных чисел мне приходится
> не часто, то практического применения библиотеки для себя
> не могу представить. Но, пробежавшись по спискам ф-ций не
> нашёл там пересечения и объединения — возможно, кому-то
> они окажутся полезными.


Вникнитесь в смысл моей задумки... Матрикс может делась абсолютно все, что можно делать над двумерными массивами вещественных чисел. Вот я и хочу узнать мнение народа: нужна ли хоть кому-то данная разработка? Если будет нужна, то надеюсь, найдутся и люди, которые помогут сделать и пересечение множеств и все что угодно.
Моя логика такова: кто работал с матлабом, тот сможет достойно оценить матрикс. Просто я считал почему-то, что с матлабом работали практически все. Или я ошибался? Не знаю... Но мне кажется, что идея хорошая - создать быстрое, удобное средство, с помощью которого программист в Дельфи сможет быстро реализовать то, что раньше можно было сделать только в матлабе. Быстро реализовать: это минимум строк кода, максимум выразительности кода, возможность в любой момент сохранить результаты в файл, под рукой всегда все необходимые операции, и все эти операции быстры, надежны (т.к. переписывались заново несколько раз).
Пока есть только менеджер массивов, и основной упор делался на удобство использования матрикса программистом.


> от, в общем-то, мое скормное мнение. Надеюсь ничего, что
> в несколько негативном ракурсе.


Ничего :) Ценная критика!!!


 
Zeqfreed ©   (2006-01-05 10:40) [30]

Loginov Dmitry ©   (05.01.06 9:54) [29]

> как еще можно набросать пол-сотни панелей на одну
> форму, используя только стандартные компоненты Дельфи7.

Можно выбирать между TTabControl, TPageControl и TNotepad.


> Я буду очень признателен, если вы дадите совет, как
> реализовать наиболее быстрый поиск массивов.

Сравнение строк происходит весьма и весьма медленно. Думаю, что целесообразней будет воспользоваться одним из алгоритмов хэширования для поиска.


 
Loginov Dmitry ©   (2006-01-05 20:49) [31]


> Можно выбирать между TTabControl, TPageControl и TNotepad.


TTabControl - это сложно
TPageControl - было в предыдущей версии, но все вкладки не умещаются в пределах формы, а вложенные вкладки глючат при изменении размеров.
TNotepad - а что это? Ни разу не слышал.


> Сравнение строк происходит весьма и весьма медленно. Думаю,
>  что целесообразней будет воспользоваться одним из алгоритмов
> хэширования для поиска.


То есть как это медленно? Сравнение строк происходит побайтно.
На счет хэширования... за счет чего здесь может происходить ускорение? ИМХО, процесс хэширования занимает какое-то время. Есть функция поиска массива Find(S: string). Как я понимаю, в начале функции требуется вычислить хэш, после чего далее следует искать в списке именно его. Вот в нашем случае как долго будет вычисляться хэш?. Длина строки от 1 до 32 символов. Символы могут быть следующие: ["a".."z", "A".."Z", "0".."9", "_", "$"]. Как определить необходимую и достаточную длину хэша (2 байта, 4 байта, 8 байт или 16 байт)? Вообще, судя по числу возможных комбинаций, длина хеша должна составлять не менее 256 бит (32 байта). Но... длина хэша постоянная (32 байта), а длина строки может быть любой. Так что ускорения я здесь не наблюдаю. Извеняюсь за возможную некомпетентность в криптографии :) Поправьте меня, если я не прав.


 
Zeqfreed ©   (2006-01-05 22:09) [32]

Loginov Dmitry ©   (05.01.06 20:49) [31]

type
 PHash = ^THash;
 THash = record
  strIdx, hash_val : Cardinal;
 end;

...

var
...
 string_arr : array[0..999] of String;
 hash_arr : TList;

...

procedure GenerateStrings();
var
i, j : Integer;
begin
Randomize();
for i := 0 to 999 do begin
 for j := 1 to Random(30) + 1 do
  string_arr[i] := string_arr[i] + Chr(Random(27)+65);
end;
end;

function SimpleHash(const Key : String; tableSize : Integer) : Cardinal;
var
i : Integer;
Hash : Cardinal;
begin
Hash := 0;
for i := 1 to length(Key) do
 Hash := ((Hash * 17) + Ord(Key[i])) mod tableSize;
Result := Hash;
if (Result < 0) then Inc(Result, tableSize);
end;

function Compare(Item1, Item2: Pointer): Integer;
begin
if THash(Item1^).hash_val < THash(Item2^).hash_val then
 Result := -1
else if THash(Item1^).hash_val = THash(Item2^).hash_val then
 Result := 0
else
 Result := 1;
end;

procedure GenerateHash();
var
i : Integer;
hash : PHash;
time : DWORD;
begin
time := GetTickCount();

for i := 0 to 999 do begin
 New(hash);
 hash^.strIdx := i;
 hash^.hash_val := SimpleHash(string_arr[i], 51);
 hash_arr.Add(hash);
end;
hash_arr.Sort(Compare);

time := GetTickCount - time;
Form1.Memo1.Lines.Add(Format("Generating hash values: %d ms", [time]));
end;

{ф-ция основана на коде Джулиана Бакнелла}
procedure FindString(const Str : String);
var
i : Integer;
begin
for i := 0 to 999 do
 if Str = string_arr[i] then Break;
end;

procedure FindHash(const Str : String);
var
hash : PHash;
cmp, L, R, M : Integer;
begin
New(hash);
hash^.hash_val := SimpleHash(Str, 51);
hash^.strIdx := 0;

try

 L := 0;
 R := pred(hash_arr.Count);
 while (L <= R) do begin
  M := (L + R) div 2;
  cmp := Compare(hash_arr.List^[M], hash);
  if (cmp < 0) then
   L := succ(M)
  else if (cmp > 0) then
   R := pred(M)
  else begin
   //Result := M
   Exit;
  end;
 end;

//if we are here then Str was not found  
finally
 Dispose(hash);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
i : Integer;
time : DWORD;
begin
hash_arr := TList.Create();
try
 GenerateStrings();
 GenerateHash();

 time := GetTickCount;
 for i := 0 to 9999 do begin
  FindString(string_arr[Random(1000)]);
 end;
 time := GetTickCount - time;
 Form1.Memo1.Lines.Add(Format("Searching 10000 random existing strings by string values: %d ms", [time]));

 time := GetTickCount;
 for i := 0 to 9999 do begin
  FindHash(string_arr[Random(1000)]);
 end;
 time := GetTickCount - time;
 Form1.Memo1.Lines.Add(Format("Searching 10000 random existing strings by string values: %d ms", [time]));

 for i := 0 to 999 do Dispose(hash_arr.List^[i]);
finally
 hash_arr.Free;
end;
end;


Прошу сильно за качество кода не пинать. Писал — лишь бы поскорей :) Думаю общий смйсл понятен. Результаты не особо точные, но тенденция заметна. Причем, стоит заметить, что сортировка в TList не самая оптимальная ;) На моем компьютере результаты получились следующие:

Generating hash values: 0 ms
Searching 10000 random existing strings by string values: 141 ms
Searching 10000 random existing strings by string values: 16 ms


Также обращаю внимание на то, что в коде не предусмотрено разрешение возможных коллизий хэшей.


 
Zeqfreed ©   (2006-01-05 22:14) [33]

Zeqfreed ©   (05.01.06 22:09) [32]
Ну вот :(
Опять придется писать комментарии к своему же посту :)


> {ф-ция основана на коде Джулиана Бакнелла}

Естественно, этот комментарий относится к ф-ции FindHash.


> "Searching 10000 random existing strings by string
> values

Разумеется, во втором случае “by string values” следует читать как “by hash values”.

Если что ещё не доглядел — прошу прощения.


 
Loginov Dmitry ©   (2006-01-05 22:42) [34]

Я вот подумал... Да фиг с ними, с этими коллизиями. Можно же проверить так: ищем хэш, совпадает - проверяем строки на совпадение, строки не совпадают - продолжаем искать хэш. За код спасиба! Завтра изучу :)

А так, кроме поиска строк, остальное потянет? Для ускорения работы я старался делать все, что было в моих силах, но вместе с тем старался чтобы код был максимально прост. Чего стоило сделать функции CalcFunc и CalcFunc2!!! Я их раз пять переписывал, но зато теперь они действительно универсальны ^)))))

Кстати, кто хорошо разбирается в анализе текстовых файлов, у меня вопрос. Никак не могу понять, почему время посимвольного анализа текстового файла (ок. 5 Мбайт) с помощью функции Read(), такое же, как и в случае загрузки этого же файла в поток TMemoryStream и последующего применения функции Read()? Насколько я понял, перед началом чтения файл кэшируется в оперативной памяти, потому и скорость высокая. Или второй вариант - поток попросту тормозит. Как ВЫ считаете?????


 
Fenik ©   (2006-01-05 23:44) [35]

Почему везде Real, а не Double?
В процедуре TWorkspace.FSaveArrayToBinFile:

1. Вместо
while Name[Length(Name)] = #0 do Delete(Name, Length(Name), 1);

имхо, явно предпочтительнее

N := Length(Name) - 1;
while (PChar(Name)[N] = #0) and (N >= 0) do Dec(N);
Name := Copy(Name, 1, N + 1);


2. Конструкцию
 if DataType = 0 then
   FS.Write(Pointer(Adr)^, Rows * Cols * 8) else
 begin
   MStream.SetSize(0);
   ArSize := Rows * Cols - 1;
   case DataType of
     1, 2: begin
             MStream.SetSize(Rows * Cols * 1);
             for J := 0 to ArSize do
             begin
               R := Real(Pointer(Adr + (J shl 3))^);
               TByte := Trunc(R);
               MStream.Write(TByte, 1);
             end;
           end;
     3, 4: begin
             MStream.SetSize(Rows * Cols * 2);
             for J := 0 to ArSize do
             begin
               R := Real(Pointer(Adr + (J shl 3))^);
               TWord := Trunc(R);
               MStream.Write(TWord, 2);
             end;
           end;

     5, 6: begin
             MStream.SetSize(Rows * Cols * 4);
             for J := 0 to ArSize do
             begin
               R := Real(Pointer(Adr + (J shl 3))^);
               TDWord := Trunc(R);
               MStream.Write(TDWord, 4);
             end;
           end;

   end; // of case
   // Записываем поток MStream в FS
   FS.Write(Pointer(MStream.Memory)^, Rows * Cols * ByteCnt);
 end;


Я бы заменил на


 ArSize := Rows * Cols;
 if DataType = 0 then
   FS.Write(Pointer(Adr)^, ArSize * 8) else
 begin
   MStream.SetSize(ArSize * ByteCnt);
   case DataType of
     1, 2: for J := 0 to ArSize - 1 do
           begin
             MStream.Write(Byte(Trunc(Real(Pointer(Adr)^))), ByteCnt);
             Inc(Adr, 8);
           end;
     3, 4: for J := 0 to ArSize - 1 do
           begin
             MStream.Write(Word(Trunc(Real(Pointer(Adr)^))), ByteCnt);
             Inc(Adr, 8);
           end;
     5, 6: for J := 0 to ArSize - 1 do
           begin
             MStream.Write(DWord(Trunc(Real(Pointer(Adr)^))), ByteCnt);
             Inc(Adr, 8);
           end;
   end; // of case
   // Записываем поток MStream в FS
   FS.Write(Pointer(MStream.Memory)^, MStream.Size);
 end;

--------------------------------

Функцию GetElemType я бы переписал так:

function TWorkspace.GetElemType(const Name: string): Byte;
const
 MinOfType: array [1..6] of Int64 =
   (Low (Byte), Low (Shortint), Low (Word), Low (Short), Low (DWord), Low (Integer));
 MaxOfType: array [1..6] of Int64 =
   (High(Byte), High(Shortint), High(Word), High(Short), High(DWord), High(Integer));
var
 I, Rows, Cols, Adr: Integer;
 R, MaxEl, MinEl: Real;
begin
 Result := 0;
{ Сразу находим мин. и макс. элементы, чтобы лишний раз не сканировать массив }
 MinEl :=  MaxDouble;
 MaxEl := -MaxDouble;
 Adr := GetAddress(GetSize(Name, Rows, Cols));
 for I := 0 to Rows * Cols - 1 do begin
   R := Real(Pointer(Adr)^);
   if Frac(R) <> 0 then Exit;
   if R > MaxEl then MaxEl := R
     else
   if R < MinEl then MinEl := R;
   Inc(Adr, 8);
 end;
 if MinEl > MaxEl then MinEl := MaxEl;

 for I := 1 to 6 do
 if (MinEl >= MinOfType[Result]) and (MaxEl <= MaxOfType[Result]) then
 begin
   Result := I;
   Break;
 end;
end;


Функцию GetMinMax вот так:

procedure TWorkspace.GetMinMax(Name: string; var MinVal, MaxVal: Real);
var
 I, Adr: Integer;
 R: Real;
begin
 MinVal :=  MaxDouble;
 MaxVal := -MaxDouble;
 Adr := GetAddress(Name);
 for I := 0 to GetSize(Name) - 1 do
 begin
   R := Real(Pointer(Adr)^);
   if R > MaxVal then MaxVal := R
     else
   if R < MinVal then MinVal := R;
   Inc(Adr, 8);
 end;  
 if MinVal > MaxVal then MinVal := MaxVal;
end;


В TWorkspace.InsertCols можно оптимизировать цикл до такого:

 Cols1 := Cols1 shl 3;
 Cols2 := Cols2 shl 3;
 ColsR := ColsR shl 3;
 Col := (Col - 1) shl 3;
 Move3Count := Cols2 - Col + 16;
 Move3DestShift := Col + Cols1;
 for I := 1 to RowsR do
 begin
   Move(Pointer(Adr2)^, Pointer(AdrR)^, Col);
   Move(Pointer(Adr1)^, Pointer(AdrR + Col)^, Cols1);
   Move(Pointer(Adr2 + Col)^, Pointer(AdrR + Move3DestShift)^, Move3Count);
   Inc(Adr1, Cols1);
   Inc(Adr2, Cols2);
   Inc(AdrR, ColsR);
 end;


В TWorkspace.CalcFunc2:

   if IsValue1 then
   for I := 0 to ElCount do
   begin
     Real(Pointer(dAdr)^) := Func(Value1, Real(Pointer(Adr2)^));
     Inc(dAdr, 8);
     Inc(Adr2, 8);
   end else
   if IsValue2 then
   for I := 0 to ElCount do
   begin
     Real(Pointer(dAdr)^) := Func(Real(Pointer(Adr1)^), Value2)
     Inc(dAdr, 8);
     Inc(Adr1, 8);
   end else
   for I := 0 to ElCount do begin
     Real(Pointer(dAdr)^) := Func(Real(Pointer(Adr1)^), Real(Pointer(Adr2)^));
     Inc(dAdr, 8);
     Inc(Adr1, 8);
     Inc(Adr2, 8);
   end;


Ну, идея по поводу замены умножения счетчиков (I shl 3) на смещение адреса (Inc(Adr, 8)), думаю ясна? Это все же быстрее: один Inc против "+" и shl (хотя не знаю, как там оптимизатор это преобразует). Да и смотрится лучше, имхо. В Матриксе много таких циклов, да еще и с другими лишними вычислениями (в процедурах CopySubmatrix, PastSubmatrix, MulMatrix, IsEqual, CopyCutCols, CopyCutRows, AddCols, Transpose, LoadFromBinFile и т.д.).

Еще говорят, что доступ к символу строки путем PChar(str)[I-1] быстрее, чем просто str[I], поэтому например в функции TWorkspace.IsTrueName пишем    
for I := 1 to Len-1 do
 if not (PChar(Name)[I] in ["A".."Z", "a".."z", "0".."9", "_"]) then Exit;

(При PChar отсчет идет с нуля.)


 
zapadlinskoe   (2006-01-06 00:35) [36]


> Loginov Dmitry ©   (03.01.06 14:54)  [1]
> Может ли ядро матрикса быть включено в новые версии Delphi (если
> нет, что что для этого нужно сделать или с кем связаться по этому поводу)?

Нехило замахнулся!!!
Для начала смени название matrix.pas (ибо, зарезервировано уже)

_________________________________________________________
попахивает манией величия (или это действительно великий труд, который всему Borland Software Corporation не под силу:)


 
Loginov Dmitry ©   (2006-01-06 01:24) [37]

Здорово! Спасиба! Считается, про программы без недостатков не бывает, но общими усилиями мы докажем, что это заблуждение :)


> Функцию GetMinMax вот так:.............


А что будет, если наименьший элемент - первый, например: 1 2 3 4 5. По вашему алгоритму получим, что MinEl = 5.


> хотя не знаю, как там оптимизатор это преобразует


Оптимизатор это преобразует так как надо, так что и shl и Inc() работают с одинаковой скоростью, правда, проверялось это только на Дельфи 7. ...хотя конструкция Inc(Adr, 8), пожалуй, действительно понятней смотрится, чем (Adr + (I shl 3)), тут вы правы.


> В Матриксе много таких циклов, да еще и с другими лишними
> вычислениями...

Да есть такое дело. Будем постепенно от них избавляться.


> Еще говорят, что доступ к символу строки путем PChar(str)[I-
> 1] быстрее, чем просто str[I], поэтому например в функции
> TWorkspace.IsTrueName пишем    
> for I := 1 to Len-1 do
>  if not (PChar(Name)[I] in ["A".."Z", "a".."z", "0".."9",
>  "_"]) then Exit;
> (При PChar отсчет идет с нуля.)

... и это будет работать почти в полтора раза дольше :(


 
Loginov Dmitry ©   (2006-01-06 01:25) [38]


> попахивает манией величия (или это действительно великий
> труд, который всему Borland Software Corporation не под
> силу


Ты первый, кто прочитал это!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


 
Джо ©   (2006-01-06 02:28) [39]

> [38] Loginov Dmitry ©   (06.01.06 01:25)
> Ты первый, кто прочитал это!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
> !!!!!!!!!!!!!!!!

Почему же? я тоже прочитал это. Думаю примерно так же как [36]. :>


 
Loginov Dmitry ©   (2006-01-06 10:48) [40]


> Думаю примерно так же как [36]


На самом деле вопрос для меня очень важен. Поспорил с приятелем на бутылку пива, что матрикс включат в состав Дельфи. Ну что мне теперь, на пиво раскошеливаться что ли?



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

Форум: "Прочее";
Текущий архив: 2006.01.29;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.65 MB
Время: 0.054 c
15-1136803382
alexsis
2006-01-09 13:43
2006.01.29
ОРЕШНИК


15-1136444105
WondeRu
2006-01-05 09:55
2006.01.29
Впечатление от праздника - неимоверно скучно!


2-1137397081
pavel_guzhanov
2006-01-16 10:38
2006.01.29
проблемы с вычислением десятичного логарифма


15-1136457689
Харько
2006-01-05 13:41
2006.01.29
Просмотрщик текстов для мобилного телефона


2-1137172222
n0p
2006-01-13 20:10
2006.01.29
Single => String





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский