Модераторы: Snowy, MetalFan, bems, Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> вычисления в потоках, нужна помощь в рац.использ.потоков 
V
    Опции темы
Roman1
Дата 17.2.2010, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 12.10.2007

Репутация: -1
Всего: нет



Всем доброго времени суток. Прошу помочь с такой задачей. Программа производит математические вычисления нескольких функций от времени. Берется приращение времени dt,  последовательно вычисляются независимые друг от друга функции, затем  дополнительно обрабатываются и в цикле переходим к новому t+dt Пробую пустить вычисления этих функций по потокам для ускорения работы программы, так как формулы довольно громоздкие. Получилось следующее. Потоки обрабатывают глобальные переменные. После взятия нового значения времени потоки создаются через create, потом ждем их завершения через WaitFor, уничтожаем через Free, ну и обрабатываем измененыые глобальные переменные. Программа стала работать еще дольше, так как формулы большие и времени уходит много на создание потоков. А запустить методы Execute этих потоков без их уничтожения не получается. Т.е. если при запуске программы создать потоки, а  потом на каждое приращение времени вызывать их через Execute и ждать завершения, то они работают только один раз,  вызов Execute на следующем временном шаге никаких действий не производит. Читал, что нужно в этом случае применять Suspend, а потом Execute. Но в методах Execute каждого потока никаких ожиданий или циклов нет. После завершения вычислений поток, видимо, прекращает работу. Пробовал после WaitFor писать suspend, получается ошибка.
Прошу подсказать, как запускать методы Execute потоков в данном случае. Или какое-либо другое решение по ускорению вычислений.

PM MAIL   Вверх
bems
Дата 17.2.2010, 18:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



Не понял описанную структуру программы, но первое что бросается в глаза: метод Execute не предназначен для прямого вызова. Он вызывается классом автоматически при создании потока (если CreateSuspended = False) или при вызове Resume (если CreateSuspended = True). При вызове  Suspend поток останавливается где-то внутри метода Execute и для продолжения тебе нужно вызвать Resume


--------------------
Обижено школьников: 8
PM MAIL   Вверх
kami
Дата 17.2.2010, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Roman1 @  17.2.2010,  15:40 Найти цитируемый пост)
 После завершения вычислений поток, видимо, прекращает работу. 

само собой. Выход из метода Execute это прекращение жизни потока.

Один из вариантов выхода - работа через сообщения:
Код

const
  msgThreadClose=WM_USER+1;
  msgDoCalculate=WM_USER+2;
  msgCalcComplete=WM_USER+3;

TMyThread.Create(MainFormHandle:THWND);
begin
  FMainFormHandle:=MainFormHandle; // запоминаем хендл нашей формы
  inherited Create(False);
end;

TMyThread.Execute:
var
  Msg: TMSG;
  i: integer;
begin
  { Create message queue }
  PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
  // инициализируем все, что нужно для работы потока
  while not Terminated and GetMessage(msg, 0, 0, 0) do // выбираем сообщения в цикле
    begin
      if msg.hwnd = 0 then // это сообщение потоку, а не окну, созданному в его контексте
        case msg.Message of
          msgThreadClose:
            begin
              Terminate;
              break;
            end;
          msgDoCalculate:
            begin
              DoCalculate; // производим вычисления
              PostMessage(FMainFormHandle, msgCalcComplete, 0, 0); // сообщаем об этом основному потоку
            end;
        end
      else
        DispatchMessage(msg);
    end;
  // высвобождаем все ресурсы, созданные при входе в Execute 
end;


В главной (или какой-нибудь) форме:
Код

TMainForm=class(TForm);
private
  procedure CalculationComplete(var MSG:TMessage); message msgCalcComplete;

TMainForm.OnCreate(...);
begin
  FMyThread:=TMyThread.Create(Handle);
end;

TMainForm.OnNeedCalculate(...);
begin
  // запускаем поток на новый виток вычислений.
  // при этом нужно понимать, что новые вычисления не начнутся, пока не закончатся старые,
  // хоть сколько посылай сообщения - они все будут поставлены в очередь потока на обработку.
  PostThreadMessage(FMyThread.ThreadID, msgDoCalculate, 0, 0);
end;

TMainForm.CalculationComplete(var MSG:TMessage);
begin
  // здесь мы окажемся, когда поток закончит вычисления и до нашей формы дойдет его сообщение
  // об окончании вычислений.
end;

TMainForm.OnDestroy(..)
begin
  PostThreadMessage(FMyThread.ThreadID, msgThreadClose, 0, 0);
  // 
end;


Это сообщение отредактировал(а) kami - 17.2.2010, 19:01
PM MAIL WWW   Вверх
Roman1
Дата 18.2.2010, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 12.10.2007

Репутация: -1
Всего: нет



Прошу прощения, я ошибся когда писал тему. Конечно, я вызывал Execute через Resume. По поводу работы через сообщения -спасибо. Сейчас буду разбираться. 
Структура программы такая. В каждом потоке объявлены несколько функций, во всех потоках разные. Перед началом вычислений на очередном временном шаге создаем все эти потоки через Create(false), тут же в главном потоке ждем их завершения и уничтожаем. Обрабатываем измененные потоками глобальные переменные. Переходим к следующему шагу и так далее. Как я уже говорил, иначе не получается. Без уничтожения и повторного создания потока он через Resume не запускается.
PM MAIL   Вверх
Beltar
Дата 18.2.2010, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 627
Регистрация: 11.1.2006

Репутация: 0
Всего: 7



Цитата

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


Какое ускорение? Откуда? А если процессор всего один?

Честно говоря, у меня вообще есть сомнения, что вычисления всей твоей математики для одного конкретного t способны занять компьютер, даже 10-летней давности, на время большее выделяемого потоку.
И вообще что именно требуется. Обеспечить управляемость программы пока идут вычисления? Ну создай один поток, создай в нем одну рабочую ф-ию, которую будет вызывать Execute. В Execute оформи бесконечный цикл с выходом по Terminated. Набросай по ф-ии if Terminated then Exit. После выхода из рабочей ф-ии if not Terminated then Suspend; И предусмотри в дополнение к Terminated еще один флажок, по которому тоже будет осуществляться выход из рабочей ф-ии, так чтобы поток после каждой остановки не убивать. У меня это отлично работало.

А вообще http://forum.vingrad.ru/forum/topic-60076.html


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. smile(с) я, хотя может и нет
Пищущий на C++ мужик. Даже если это мужик сидит в написанном на Delphi и жрущем паскалевскую библиотеку билдере.
PM MAIL   Вверх
Roman1
Дата 18.2.2010, 13:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 12.10.2007

Репутация: -1
Всего: нет



Требуется ускорить работу. Формулы действительно большие - гиперболические синусы, косинусы и т.п. (занимают много времени, я проверял, заменял на упрощенный вариант, где плюс, минус, умножить, равно. Работает гораздо быстрее, но нет нужной точности) Шаг по времени  для нормальной точности расчетов приходится брать 1 микросекунда. Быстродействие зависит от количества объектов, которые надо обсчитать. По каждому объекту несколько глобальных переменных. Получается, если обычно объектов штук 8, то расчет до времени 15-20 секунд идет часа четыре. Правда, там по ходу строятся графики, но точки ставятся каждые 5000 шагов. Можно больше, можно меньше. В основном скорость зависит от расчетов. 
По поводу процессоров - да, на одном не ускорится.  Но сейчас кругом многопроцессорные машины, а программу, если получится сделать, предполагается распространять.
По поводу метода спасибо. Уже сижу пробую что-нибудь сделать
PM MAIL   Вверх
Roman1
Дата 18.2.2010, 17:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 50
Регистрация: 12.10.2007

Репутация: -1
Всего: нет



Всем спасибо. Ответы на мои вопросы понятны, что-то начало получаться. Ссылка тоже очень пригодилась. Тема закрыта
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.2901 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.