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




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

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Да что сказать. Код рабочий, только не оптимальный. да, он более
удобочитаемый, но про его производительность см. выше.
У тебя идет последовательное обращение к элементам массива, а индексный метод оправдывает себя только при произвольном доступе.
Насчет "Также необходимо применять указатели на память вместо ссылок, например взамен", то в большинстве случаев, Delphi сама умеет разъименовывать указатели.
И еще.
TBigArray = array[0..30000] of Integer; ограничивает размер массива в 30000 элементов. Точнее, размер ничем не ограничен, а вот адресация по индексу массива дальше 30000 не пойдет.
А конструкция
a: PInteger;
....
a := AllocMem(N * sizeof(Integer));
позволяет тебе получить любое кол-во элементов.



Партнер
 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Ray Adams
Как индикатор хода выполнения задачи ты мне посоветовал ProgressBar, но как выяняется он жутко тормозит мне все вычисления. Привожу пример: имеется исходник
Код:
procedure TForm1.BitBtn1Click(Sender: TObject);
type
  TDDA = array[1..362881,1..9] of shortint;
var
M,N: shortint;
ii,iii: integer;
i,j,jj,jjj: integer;
S: integer;
x,y: integer;
z,del: shortint;
seed: integer;
a: ^TDDA;
MM,M1: integer;

begin

M:=StrToInt(Edit1.Text);
Label1.Caption:= 'Всего комбинаций: ' + FloatToStr(Fac(M));
StartTime := GetTickCount;
GetMem(a,(Fac(M)+1)*(M+1)*4);

// Очистка главной матрици
for ii:=1 to Fac(M) do
  for iii:=1 to M do
    a^[ii,iii]:=0;

ListBox1.Items.Clear;
ListBox1.Items.BeginUpdate;

{Indikator:=TIndikator.Create(Self);
Indikator.ProgressBar1.Max:=Fac(M);
Indikator.Show;
Indikator.Update;}


// Начало цикла
for N:=1 to M do
  begin

  // Долбавление к массиву а столбец N!*1 справа.
  for i:=1 to Fac(N) do
      a^[i,N]:=N;

  // Копирование и сортировка
  for jj:=1 to Fac(N) do
    begin
    z:=(jj-1) div Fac(N-1);
    for jjj:=1 to (N-1) do
      begin
      a^[jj,jjj]:=a^[jj-z*Fac(N-1),jjj]
      end;
    {Сортировка}
    {if N=M then
      begin
      Indikator.ProgressBar1.StepIt;
      Indikator.Update;
      end;}
    del:= (jj-1) div Fac(N-1);
    seed:= a[jj,N-del];
    a^[jj,N-del]:= a^[jj,N];
    a^[jj,N]:=seed;
    end;
 end;


// Вывод конечного массива на экран
  for x:=1 to Fac(M) do
    begin
    S:=0;
    for y:=1 to M do
      begin
      S:=S + a^[x,y]*Trunc(exp((M-y)*Ln(10)))
      end;
    //b^[x]:=S;
    ListBox1.Items.Strings[x-1]:= FloatToStr(s){ + '  [' + FloatToStr(x)+ ']'};
    end;

//Indikator.Hide;
//Indikator.Free;

FreeMem(a,(Fac(M)+1)*(M+1)*4);

sek := (GetTickCount - StartTime) div 1000;
min:= sek div 60;
hour:= min div 60;
if sek<=60 then
  Label4.Caption:='Время работы = ' + FloatToStr(sek) + ' сек.'
else if sek>60 then
 Label4.Caption:='Время работы= ' + FloatToStr(min)+'мин '
 + FloatToStr(sek-60*min) + 'сек'
else if hour>=1 then
  Label4.Caption:='Время работы= ' + FloatToStr(hour) + 'ч '
  + FloatToStr(min)+'мин ' + FloatToStr(sek-60*min) + 'сек';

ListBox1.Items.EndUpdate;

end;


Время работы при N=9 составляет 2.45 мин а если убрать все прибамбасы, связанные с ProgressBar то получаю 41 сунду. Чтож это получается - Прогрессбар меня обламывает в быстродействии почти в 3.5 раза? Если N уменьшить то падение ощущается меньше - но все же?
Посоветуй что-нибудь, т.к. такая ботва меня не устраивает. Может есть другой вариант (альтернатива ПрорессБару)
или можно что-то подправить?

Добавлено спустя 1 час, 3 минуты, 4 секунды:
И в догонку еще вопрос: положим я убрал Прогрессбар, и прога считает. Как только с окна проги переключаюсь на что-нибудь другое, то при возвращении к проги она как будто в подвисшем состояниии, форма - в белом цвете, но она работает и считает и как только посчитает сразу все становиться ОК! Как мне это исправить?

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


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Halfback
1. А что ты хотел? Прогрессбар - это вызовы API функций. Они никода быстрыми не были.
2. Товя задача занята расчетами, и перерисовывать форму ей некогда. А если учесть, что WM_PAINT всегда обрабатывается последним, то причина белой формы становится понятной!

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


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Avaddon
Цитата:
Товя задача занята расчетами, и перерисовывать форму ей некогда. А если учесть, что WM_PAINT всегда обрабатывается последним, то причина белой формы становится понятной!

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

Цитата:
А что ты хотел? Прогрессбар - это вызовы API функций. Они никода быстрыми не были.

А можт есть компонент, заменяющий прогрессбар? Я могу, конечно, написать свой Прогрессбар при помощи Канвы или Чарта но заморачиваться неохота. А графический индикатор охота иметь на борту.

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


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Halfback
Потому что архиваторы выполняют вычисления в отдельном потоке, а основной поток, получив низкий приоритет рисует формочки. Тебе рекомендую того же. Только прогресс обновлять не .Position := value, а путем проставления значения в некой переменной, а в основном потоке в Application.OnIdle проставлять значение прогреса.

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


 

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

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


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Лови пример!
Код:
unit RandomCalc;

Type
 TResultForm = class(TForm)
  ProgressBar: TProgresBar;
  StartButton: TButton;
  procedure FormCreate(Sender: TObject);
  procedure StartButtonClick(Sender: TObject);
 private
  f_ThreadID: DWORD;
  f_ProgressPosition,
  f_ProgressMax:  Longint;
 public
  procedure ApplicationIdle(Sender: TObject);
 
 end;

{
 Класс TThread идет лесом - он тормозной, т.к.
 имеет оконный хэндл и процессит сообщения.
 Используем API-шные функции.
}
function CalcThreadProc(ThreadData: Pointer): DWORD; stdcall;
var
 aForm:  TResultForm;
begin
 aForm := TResultForm(ThreadData);
 { Поехали, Вычисляем кол-во итераций }
 aForm.f_ProgressMax := Кол-во_итераций;
 { Вычисляем }
 aForm.ProgressPosition := Номер_итерации:
 { Закончили вычисления }
 aForm.f_ThreadID := 0;
 Application.OnIdle := nil;
end;

procedure TResultForm.StartButtonClick(Sender: TObject);
begin
 if f_ThreadID <> 0 then Exit; // Уже идет вычисление!!!
 if CreateThread(nil,8192,@CalcThreadProc,Pointer(Self),CREATE_SUSPENDED,f_ThreadID) = 0 then
   MessageBox(Handle,'Облом при создании потока для вычислений','Серьезная ошибка',MB_OK OR MB_ICONHAND)
 else begin
  SetThreadPriority(GetCurrentThread,THREAD_PRIORITY_BELOW_NORMAL);
  SetThreadPriority(f_ThreadID,THREAD_PRIORITY_TIME_CRITICAL);   
  f_ProgressMax := 0;
  f_ProgressPosition := 0;
  ResumeThread(f_ThreadID);
  Application.OnIdle =  ApplicationIdle;
 end;
end;

procedure TResultForm.FormCreate(Sender: TObject);
begin
 f_ThreadID := 0;
end;

procedure TResultForm.ApplicationIdle(Sender: TObject);
begin
 { Да плевать на присвоение, все равно эта зверюга не будет тормозить
   процесс }
 if f_ProgressMax = 0 then Exit;
 ProgressBar.Max := f_ProgressMax;
 ProgressBar.Position := f_ProgressPosition;
end;

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


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Avaddon
Что-то сложно. Во всяком случае для меня. Я вот тоже нашел один примерчик:
Код:
var
 pi : TProcessInformation;
 si : TStartupInfo; 
 
begin
 ZeroMemory(@si,sizeof(si));
 si.cb:=SizeOf(si); 
 if not CreateProcess( PChar(lpApplicationName), //pointer to name of executable module 
 PChar(lpCommandLine), // Command line. 
 nil, // Process handle not inheritable.
 nil, // Thread handle not inheritable. 
 False, // Set handle inheritance to FALSE.   
 0, // No creation flags. 
 nil, // Use parent's environment block. 
 nil, // Use parent's starting directory.   
 si, // Pointer to STARTUPINFO structure.
 pi ) // Pointer to PROCESS_INFORMATION structure.   
 
 then begin   
 Result:=false;
 RaiseLastWin32Error; 
 Exit; 
 
 end; 
 
 while WaitforSingleObject(PI.hProcess,200)=WAIT_TIMEOUT do   application.ProcessMessages;
 CloseHandle(pi.hProcess); 
 CloseHandle(pi.hThread);
 
 // ... здесь твой код 
 
end;


Вроде все просто. В процедуру ЭТО СПАМ - ОТПРАВЬТЕ ЖАЛОБУ (синий квадрат) прямо копирую и казалось бы все... Но выскакивают ошибки о том, что не указаны(документированы) lpApplicationName и еще там что-то...
Может поможешь, т.к. все же твой пример какой-то замороченный. Более того задача немного упростилась: сделать так, чтобы форма в процессе вычислений не подвисала...

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


 

Member
Статус: Не в сети
Регистрация: 15.04.2004
Откуда: Москва
Halfback
Приведенный пример создает не поток, а процес.
И если тебя вдохновляет потом решать задачи IPC (InterProcess Communication) - то вперед.
А lpApplicationName и lpCommandLine - переменные содержащие имя запускаемого приложения и командную строка соответственно

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


 

Member
Статус: Не в сети
Регистрация: 14.08.2003
Откуда: Питер
Avaddon
Т.е. вместо
Цитата:
lpApplicationName
надо писать IpProject1.
А что писать вместо IpCammandLine ? Что значит командная строка?
Цитата:
И если тебя вдохновляет потом решать задачи IPC (InterProcess Communication) - то вперед.

А что в этом страшного? Мне главное, что в процессе форма не висла. И все.

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


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

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


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

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


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

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