Часовой пояс: UTC + 3 часа




Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 50 • Страница 1 из 31  2  3  >
  Пред. тема | След. тема 
В случае проблем с отображением форума, отключите блокировщик рекламы
Автор Сообщение
 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Народ!!! Подскажите, как на Делфи 7 сделать индикатор хода выполнения операций в программе?
Т.е. предположим у меня программа считает очень сложныее мат. выражения и обрабатывает случайные числа.
На глаз прога считает за пару секунд (при заданиии др. пар-ров по разному). Так вот как мне зделать индикатор выполнения задачи?
Можно графически или в процентах. Без разници.

_________________
Лучшая зашита - это нападение.



Партнер
 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Halfback Создаеш форму, на нее кладеш progressbar. Также заранее просчитай как двиагрть прогресс. Тоесть от 1 до 100, это все твои операции должны быть.
Дальше допусти у тебя цикл где все это и выполняется. До начала цикла, создаеш форму
frmProgress=TFrmProgress.Create(Self);
frmProgress.ProgressBar1.Max:=тут чегото максимальное, сам должен вычислить
frmProgress.Show;
frmProgress.Update;
//начинаем цикл
for ___________
begin
//тут идут твои вычисления
frmProgress.progressBar1.StepI;
end;
frmProgress.Free;


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Цитата:
frmProgress=TFrmProgress.Create(Self);
frmProgress.ProgressBar1.Max:=тут чегото максимальное, сам должен вычислить
frmProgress.Show;
frmProgress.Update;
//начинаем цикл
for ___________
begin
//тут идут твои вычисления
frmProgress.progressBar1.StepI;
Цитата:
Application.ProcessMessages; // Неплохо бы, а то прогресс бар не перерисуется...

end;
frmProgress.Free;

_________________
Цель жизни - d20 по жизни...


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Avaddon
frmProgress.progressBar1.StepI;
frmProgress.progressBar1.Update;
и все :)
Если же Application.ProcessMessages; то надо будет учитывать что все остальные элементы будут работать. Тоесть логику надо будет учесть :)


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Ray Adams
Ага, особенно это полезно если есть пимпа "Прервать выполнение".

_________________
Цель жизни - d20 по жизни...


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams
А можно небольшой примерчик? Например генерация случ. чисел по какому-нибудь закону..... Ато я что-то не врубаюсь куда что писать и создавать.

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Цитата:
Например генерация случ. чисел по какому-нибудь закону

Я что-то не понял. Тебе надо генерацию или то как выводить прогресс бар???


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Ray Adams
А ты ему пример с Random дай.. :) Тоже по "какому-нибудь" закону производится...

_________________
Цель жизни - d20 по жизни...


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams
Мне вот что нужно: прога по специальному алгоритму генерирует случ.числа а потом их специальным образом сортирует. Эта операция у меня выполняется примерно 3-4 секунды. Короче - вот листинг:

unit Unit1;

interface

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

type
TForm1 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
BitBtn1: TBitBtn;
ListBox1: TListBox;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
Label2: TLabel;
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.BitBtn2Click(Sender: TObject);
begin
Form2.Visible:= true;
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
begin
close;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);

Label Unix;

var
N,NN: integer;
i,j,v,m,k: integer;
S: integer;
R: array[1..10] of integer;
a: array[0..200000] of integer;

begin

Form1.ListBox1.Items.Clear;

N:= StrToInt(Edit1.Text);
NN:=1;
a[0]:=0;
for i:=1 to N do
begin
NN:= NN*i ;
end;
Label2.Caption:= 'Всего вариантов перестановок: ' + FloatToStr(NN);


for j:=1 to NN do
begin
Unix:
S:=0;
for v:=1 to N do
begin
R[v]:=1+Random(N);
for k:=1 to (v-1) do
begin
if R[v]=R[k] then GoTo Unix else
end;
S:= S + R[v]*Trunc(exp(v*ln(10)))
end;
a[j]:=Trunc(S/10);
for m:=1 to j-1 do
begin
if a[j]= a[m] then GoTo Unix else
end;

Form1.ListBox1.Items.Strings[j-1] := FloatToStr(j)+ ': ' + FloatToStr(a[j]);

end;

end;

end.

Если задавать N=4 или 5 то прога считает и выводит на листбокс комбинации чисел быстро. А вот если N=7 то надо ждать 3-4 секунды. Так вот мне нужен типа оценщика времени выполнения этих операций (ну например как в RAR-е мы видим ход выполнения архивации).
Но вот еще вопрос: почему когда я ставлю N=8 и более прога зависает?
И еще. Что такое прогрессбар, как вводить и для чего нужен? В доступной литературе ничего на этот счет не нашел...

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Цитата:
Но вот еще вопрос: почему когда я ставлю N=8 и более прога зависает?

Ну ктож знает что ты там наделал :) Код твой, дебагер в дельфи есть, вперед :)
А код для прогресса я тебе сейчас сделаю.

Добавлено спустя 9 минут, 38 секунд:
При установки в 8 у меня ушло около 3 минут на создание списка, ничего не подвисает. Просто логику доработай для ускорения создания списке. Так как при 8 вариантов подстановок больше 40 000.

Добавлено спустя 3 минуты, 36 секунд:
Короче лови исходник с доработкой небольшой. При установке в 7 тратится не больше 2 секунд. Все что ниже у меня пролетает незаметно для глаза.
Заметь что я добавил ListBox1.Items.BeginUpdate; в начале и ListBox1.Items.EndUpdate;
если у тебя очень много данных пишутся в ListBox то лучше сперва заблокировать его, сдлелать все апдейты и уж потом разблокировать. Получиш очень хороший прирост в скорости.

http://cp.people.overclockers.ru/cgi-bi ... ogress.rar

Добавлено спустя 1 минуту, 4 секунды:
Да и еще, тебе не кажется что else тут вообще лишний?

Код:
             
for m:=1 to j-1 do
             begin
                  if a[j]= a[m] then GoTo Unix else
             end;

также как и тут
Код:
                  for k:=1 to (v-1) do
                  begin
                       if R[v]=R[k] then GoTo Unix else
                  end;


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams
Спасибо! Прикрутил фичи к своей проге! Все прекрано работает! Как раз то что я хотел!
А оптимизацией кода я займусь....

Цитата:
При установки в 8 у меня ушло около 3 минут на создание списка, ничего не подвисает

У меня заняло примерно 1.5 минуты.

Цитата:
Да и еще, тебе не кажется что else тут вообще лишний?

Да, так оно и есть.

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Ну и отлично :).


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Есть такой исходничек:

Цитата:
procedure TForm1.BitBtn2Click(Sender: TObject);
Label Unix2;
var
N,NN: integer;
i,j,v,m,k,vv: integer;
S: integer;
RR: integer;
U: array[1..10] of shortint;
R: array[1..10] of shortint;
a: array[0..200000] of integer;

begin
ListBox1.Items.BeginUpdate;
ListBox1.Items.Clear;
N:= StrToInt(Edit1.Text);
//if N>=10 then ShowMessage('Неправильно введено число N');
NN:=1;
for i:=1 to N do
begin
NN:= NN*i ;
end;
Label1.Caption:= 'Вариантов перестановок: ' + FloatToStr(NN);
frmProgress:=TfrmProgress.Create(Self);
frmProgress.ProgressBar1.Max:=nn;
frmProgress.Show;
frmProgress.Update;
for j:=1 to NN do
begin
frmProgress.ProgressBar1.StepIt;
frmProgress.Update;
Unix2:
for m:=1 to N do
U[m]:=m;
for v:=N downto 1 do
begin
RR:=Random(v)+1;
R[N-v+1]:=U[RR];
for k:=RR to N do
begin
U[k]:=U[k+1];
end;
end;
S:=0;
for vv:=1 to N do
S:= S + R[vv]*Trunc(exp((N-vv)*ln(10)));
a[j]:=Trunc(S);
for m:=1 to j-1 do
begin
if a[j]= a[m] then GoTo Unix2 else
end;
ListBox1.Items.Strings[j-1] :=FloatToStr(a[j])+' ['+ FloatToStr(j)+']';
end;
frmProgress.Hide;
frmProgress.Free;
ListBox1.Items.EndUpdate;
end;

Но вот я не могу понять, почему когда я пищу для массива a верхний предел 300000 и более то прога при работе вылетает? Как это исправить т.к. хочется получить генерацию 9-ти значных РАЗНЫХ чисел а 9!=362880?

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
a: array[0..200000] of integer; может увеличить?


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams
В том то и дело что никак не увеличить. Максимум 256000 а далее прога вылетает. Как это поправить?

И еще вот что... Как увеличить производительность проги? Пробовал ставить ей Реал-Тайм/Hihg приоритеты - но дивидендов от этого вообще никаких. Только система подвисает.

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Halfback какая ось стоит?
Производительность увеличивается такими вариантами
1 переписываеш код более оптимизировано
2 часть вычислений перекидываеш на ассемблер
3 апгрейд компа.

Цитата:
Максимум 256000 а далее прога вылетает. Как это поправить?

Потому что Stack Overflow! Кто же создает такого размера переменные в теле функции??? А нафига были созданы динамические массивы?
Вот тебе кусок кода с использованием динамического масства. Но учти! Динамические массивы начинаются с индекса 0. А так как ты использовал массивы 1.. и до. То выделять тебе надо будет на 1 больше чем надо, чтобы не менять сам код.
Только я их кода пока вырубил progressbar, ну сам разюберешся думаю :)


Код:
procedure TForm1.Button1Click(Sender: TObject);
Label Unix2;
var
N,NN: integer;
i,j,v,m,k,vv: integer;
S: integer;
RR: integer;
U: array[1..10] of shortint;
R: array[1..10] of shortint;
a: array of integer;

begin

     SetLength(a,300001);
     ListBox1.Items.BeginUpdate;
     ListBox1.Items.Clear;
     N:= StrToInt(Edit1.Text);
     //if N>=10 then ShowMessage('Íåïðàâèëüíî ââåäåíî ÷èñëî N');
     NN:=1;
     for i:=1 to N do
     begin
          NN:= NN*i ;
     end;
     Label1.Caption:= 'Âàðèàíòîâ ïåðåñòàíîâîê: ' + FloatToStr(NN);
     for j:=1 to NN do
     begin
          Unix2:
          for m:=1 to N do U[m]:=m;
                      for v:=N downto 1 do
                      begin
                           RR:=Random(v)+1;
                           R[N-v+1]:=U[RR];
                           for k:=RR to N do
                           begin
                               U[k]:=U[k+1];
                           end;
                      end;
          S:=0;
          for vv:=1 to N do
          S:= S + R[vv]*Trunc(exp((N-vv)*ln(10)));
          a[j]:=Trunc(S);
          for m:=1 to j-1 do
          begin
               if a[j]= a[m] then GoTo Unix2;
          end;
          ListBox1.Items.Strings[j-1] :=FloatToStr(a[j])+' ['+ FloatToStr(j)+']';
     end;
     ListBox1.Items.EndUpdate;
     SetLength(a,0);
end;


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams

Спасибо!!! Все вроде работает. При N=9 прога уже как 30минут считает.

Цитата:
1 переписываеш код более оптимизировано

В каком смысле оптимизированно? Единственно, что тут можно оптимизировать, так это следующий кусок кода:
Цитата:
for m:=1 to N do U[m]:=m;
for v:=N downto 1 do
begin
RR:=Random(v)+1;
R[N-v+1]:=U[RR];
for k:=RR to N do
begin
U[k]:=U[k+1];
end;
end;

Более того как помнишь при первом коде когда N=8 прога генерила числа 1.5 минуты а теперь 30сек.
А оптимизацию остального я не вижу возможным.

Цитата:
часть вычислений перекидываеш на ассемблер
,
Я ассемблер вообще не знаю. Может поможешь с этими вставками и дай, если знаешь, ссылочки на это дело.

Цитата:
часть вычислений перекидываеш на ассемблер

Думаю, что этот вариант для меня самый неудобный. Тем более, что виноват в скорости больше сам компилятор в Делфи чем мой проц и FSB.

По поводу производительности вычислений я вот еще что думаю. Я слышал, что можно использовать отдельный поток памяти для прогаммы с помощью Threat. И еще для работы проги вроде можно выделять какую-то часть ОЗУ. Только вот как все это применять я тоже не знаю. Что по этому поводу можешь сказать?

Да, ище. Как мне поставить секундомер выполнения операций? (Т.е. за какое время, например при N=8, прога будет генерить комбинации чисел и выведет их на ProgressBar ).

_________________
Лучшая зашита - это нападение.


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Halfback
Есть такая функция. GetTickCount(). Возвращает кол-во мс прошедших с момента старта системы.
Те:
var
StartTime, Duration : Integer;
begin
StartTime := GetTickCount;
.....
Duration := (GetTickCount - StartTime) div 1000; // Время выполнения в секундах
Все здорово, но можешь нарваться на переход через 2 в 32 (т.е. система проработала меньше этого времени до старта и больше по окончании работы ).

Оптимизация.
Все for меняй на while (т.к. у тебя одной из конечных границ есть 1, то все можно свести к банальной проверке на больше/меньше 0).
Все + заменяй на inc(). Не адресуйся к массиву по индексу, а вычисляй указатель. Вот тебе кусок примера:
var
P: PShortInt;
....

m:= 1;
p := @U;
while(N-m > 0) do begin // for m:=1 to N do U[m]:=m;
p^ := m;
inc(m);
inc(p);
end;


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Avaddon
Спасибо за GetTickCount. Все работает. Только вот на строчку
Цитата:
Duration := (GetTickCount - StartTime) div 1000;

выдает предупреждение:
Цитата:
[Warning] Unit1.pas(226): Combining signed and unsigned types - widened both operands

это что-то типа 'комбинируют знаковые и незнаковые типы - оба широкие операнды'?

Не мог бы прокоментировать следующие строки приведенного тобой примера:
Цитата:
P: PShortInt;
p := @U;
p^ := m;


Добавлено спустя 37 минут, 20 секунд:
Ray Adams
Цитата:
какая ось стоит?

WinXP SP1

После 40-ка минут работы прога просто виснет (диспетчер задач пишет, что прога не отвечает), хотя ProgressBar почти уже 100%. Что за крендель? Как можно исправить сию ситуацию?

_________________
Лучшая зашита - это нападение.


 

Advanced member
Статус: Не в сети
Регистрация: 09.06.2003
Откуда: USSR
Цитата:
После 40-ка минут работы прога просто виснет (диспетчер задач пишет, что прога не отвечает), хотя ProgressBar почти уже 100%. Что за крендель? Как можно исправить сию ситуацию?

Все нормально, просто при больших числах у тебя внутренний цикл очень большой. И потому с виду зависает.


Цитата:
тем более, что виноват в скорости больше сам компилятор в Делфи чем мой проц и FSB.

Извини за резкость, но не пори чуши плиз :). Delphi делает очень хорошо оптимизированный код, также как и луюбой другой язык. Можеш глянуть на него в ассемблерном виде, написано так, как если бы кто-то писал именно на асме :).


Цитата:
Я слышал, что можно использовать отдельный поток памяти для прогаммы с помощью Threat

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

Добавлено спустя 17 минут, 8 секунд:
КСтати может опишет, что же ты этим кодом добиваешся то? А то не понятно что ты хочеш добиться и как сортируеш. Может сперва надо создать массив и только после окончания его создания , сортирнуть , скажем бинарным способом?


Показать сообщения за:  Поле сортировки  
Начать новую тему Новая тема / Ответить на тему Ответить  Сообщений: 50 • Страница 1 из 31  2  3  >
-

Часовой пояс: UTC + 3 часа


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

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


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

Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB | Kolobok smiles © Aiwan