Young Coder |
Отправлено: 31.07.2003, 17:45 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 34
|
Реально, есть цикл... не важно что в нем...
и если просто запустить его, то он выполнятется за 10 секунд.
Но логично, что процессы которые длятся более 3 секунд должны быть показаны (индикация) пользователю... чтобы он не подумал что прога висит... но стоит шлепнуть ProgressBar и показывать на нем чего да как... — прога выполняет скрипт примерно в два, три раза долше.
Понятно, что это из-за визуализации... НО, черт, как это обойти?
|
|
Admin |
Отправлено: 31.07.2003, 22:33 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Конечно визуализация происходит медленно, но вряд-ли
отбражение ProgressBar увеличивает время в 3 раза
(с 10 до 30 секунд), наверное дело в чем то еще ?
Возможно:
1/ Идет сложный расчет, текущего значения ProgressBar,
на это тратится процессорное время.
2/ А вы случайно в этом цикле не выводите-ли что либо еще
на экран ? (не только ProgressBar) и прыгает с вывода
ProgressBar на вывод-перерисовку чего-то другого.
3/ И не запихнут-ли у вас цикл в отдельный поток ?
Если зипихнут, то время будет тратиться на переключение
между потоками.
|
|
Георгий |
Отправлено: 31.07.2003, 23:39 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Young Coder
со временами ты конечто загнул!
Хотя кто тебя знает — вдруг ты на 386DX-40 + 8Mb RAM + Trident 512kb сидишь?
Индикатор действительно рисуется медленно... А ты индикатор двигай шагами — например по 20% — пользователю разницы между 1% и 20% нет ни какой, а у тебя в 20 раз меньше затрат времени на перерисовку!
Admin
с № 1 могу согласиться :-))
с № 2 может Young Coder согласиться :-]]
с № 3 не согласен: ;-]]
3.1 если цикл с TProgressBar`ом в потоке, то время действительно будет тратиться, но не на переключение задач, а на синхронизацию с основным потоком (TProgressBar — VCL обьект и не очень должен любить работу не из основного потока).могу ошибаться — так что если не прав поправьте
3.2 переключение задач... Ах — моя любимая тема...
с того момента как Intel реализовала поддержку многозадачности на аппаратном уровне, затраты времени свелись практически к нулю. Зубков говорит, что у P5 на это уходит около 85 тактов (386 — ~310). Да и MS Windows не очень часть задачи переключает — кажется каждые 30ms (переключение по таймеру при равных приоритетах и отсутствии активных задач с большим приоритетом). => 85 округляем до 100 и умножаем на число переключений в секунду 1/0,03 = 3333 тактов на переключение задач => для P5-100MHz это 0,033ms т.е. 999,96667 ms из секунды, что соответствует 99,996667% машинного времени P5, остаётся для других задач.
так что потоки можно сотнями штамповать! Но надо быть осторожным — у мелкомягких свой взгляд на многозадачность и потоки одной задачи кажется вообще не конкурируют между собой — кто первым занял процессор, тот и будет его использовать, а остальные потоки ждут... |
|
Young Coder |
Отправлено: 01.08.2003, 10:10 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 34
|
Спасибо за ответы, а как вы смотрите, если в качестве альтернативы просто выводить _типа_форму_ с тикающими часиками?
- не надо просчитывать прогресс...
- юзер видит что что-то делается...
Как вы считаете?
|
|
Admin |
Отправлено: 01.08.2003, 10:45 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Георгий
QUOTE |
3.1 если цикл с TProgressBar`ом в потоке, то время действительно будет тратиться, но не на переключение задач, а на синхронизацию с основным потоком (TProgressBar — VCL обьект и не очень должен любить работу не из основного потока).
|
Да, именно это и имел ввиду, особенно как реализованы потоки
в C++Builder (точнее синхронизация с VCL объектами) через
Synhronize().
QUOTE |
так что потоки можно сотнями штамповать!
|
Кхм...
"Также, при создании потоков следует учитывать, что слежение за слишком многими потоками потребляет процессорное время; рекомендованный предел — 16 активных потоков на процесс на системах с одним процессором."
(Из перевода Help-а к C++Builder или еще не помню откуда)
Отредактировано Admin — 01/08/2003, 11:48
|
|
Георгий |
Отправлено: 01.08.2003, 11:06 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
если у тебя пользователи пассивные то так и делай, а если у тебя идёт очень важный процесс, то лучше прогрессбар — так пользователям спокойнее
Admin
да это из help`a к BCB, но посмотри сколько потоков сам Microsoft делает — у него в среднем 30 на одну задачу...
А число активных — ну с таким телом:
for (int i=0;i<1000000;i++);
в 98-м больше 4-х одновременно не работают
а в XP больше 2-х одновременно не работают
вот и получается то, о чём я в последнем предложении предыдущего постинга говорил
кстати проверить это просто(свой код, к сожалению, не могу найти):
CODE |
потока, с полем типа volatile int* ptr
и таким кодом:
for (int i=*ptr;i;i--)
*ptr=i
в главной форме пишем:
const size_v=15;
votalile int values[size_v];
TEdit* Edits[size_v];
обработчик таймера:
for (i=0;i<size_v;i++) Edits[i]->Text=values[i];
обработчик кнопки:
Timer->Enabled=false;
for (i=0;i<size_v;i++)values[i]=1000000;
Edits[0]=Edit1;
Edits[1]=Edit2;
...
Edits[14]=Edit15;
Timer->Enabled=true;
for (i=0;i<size_v;i++)
{
TMyThread* t=new TMyThread(true);
t->ptr=&values[i];
t->FreeOnTerminate=true;
};
|
и результат работы этой программы наглядно покажет, как время разделяется между процессами одной задачи. У меня, как я уже говорил, больше 4-х потоков одновременно не выполнялось (это по значениям Edit видно)
А в том случае, когда потоки находятся в режиме ожидания — времени на их обслуживание вообще не должно тратиться.
Так что формально я прав — потоков можно делать сколько угодно, но фактически не прав — одновременно работать больше n (где n определяется экспериментально) не будут.
Отредактировано Георгий — 01/08/2003, 12:43 |
|
Admin |
Отправлено: 01.08.2003, 17:39 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
QUOTE |
Admin
да это из help`a к BCB, но посмотри сколько потоков сам Microsoft делает — у него в среднем 30 на одну задачу
|
Так это большая разница !
Наверняка Microsoft организует работу потоков через
функции Win32Api (а то и ниже)
CreateThread() и т.д., а не через TThread
Тоже самое можно реализовать и в C++Builder -
создаете и полностью работаете с потоками через
функции Win32API, только не обращайтесь к VCL объектам !
(у меня знакомый создает в отдельном потоке окно/окна
через WinApi и работает с ним в отдельном потоке/потоках ) -
разумеется работает быстрее и правильнее.
|
|
Георгий |
Отправлено: 02.08.2003, 11:15 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Admin
что бы у читающих не сложилось впечатление, что TThread, использовать нельзя или не имеет смысла:
TThread скорее всего банальная обьектная обёртка для того же CreateThread, так что создание потоков через TThread и CreateThread — эквивалентные варианты (в том числе в плане ограничений)
VCL — да это у Borland получился ёжик — вроде работает, но трогать нельзя — уколет. Поэтому, как я считаю, потоки и оконные формы реализованные в VCL несовместимы, но ни что не мешает в пределах потока использовать другие VCL обьекты, в описании которых явно не указано, что они не любят много поточность.
Так что использовать TThread можно наравне с чистым Win32API. |
|
Admin |
Отправлено: 02.08.2003, 14:50 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Мое мнение, что в 99% программ можно (и нужно) обойтись совсем
без использования потоков.
(Если конечно не пишем какую-либо игрушку или текстовый
процессор типа Word, например чтоб в отдельном потоке
проверять орфографию и т.д.)
Из оставшегося 1% конечно правильней работать через
CreateThread(), а через TThread — искать приключений, глюков и тормозов, и если сложится такое впечатление, то и хорошо,
пусть изучают Win32API — очень хорошо работа с потоками
описана в книге:
"Windows 98 Руководство разработчика" в 2-х томах
Бен Эззель, Джим Блейни (Изд. "BHV")
там и диск с примерами есть (он есть в закрытом форуме)
Использовать-же TThread конечно можно, но очень редко
когда реально это понадобиться.
Другими словами — если программа простая — потоки не нужны,
или можно использовать TThread,
если сложная — лучше использовать CreateThread(),
а при использовании TThread в сложной программе
будет очень сложно отслеживать все взаимодействие
с VCL объектами.
|
|
Георгий |
Отправлено: 03.08.2003, 17:44 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Одобрямс!
Но только почему такая не любовь к TThread? Я никаких отличий от CreateThread не заметил. |
|
Admin |
Отправлено: 03.08.2003, 21:56 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Нет, нелюбовь тут не причем, а чисто практически — скорость !
Как я уже говорил, мой знакомый написал работу с потоками
в программе через CreateThread(),
и ради интереса такой-же через TThread — разница по скорости
оказалась большая.
И кстати, также испытали компоненты — таблица в памяти -
RxMemoryData из библиотеки RXLib
и компонент kbmMEMTABLE — так вот скорость работы kbmMEMTABLE
оказалась на порядок выше, конечно, где скорость важна,
используем теперь его.
Так и с потоками. Если работать в программе типа Word,
то разницы в скорости можно и не заметить, (проверяется себе
орфография в отдельном потоке и все), а вот если
есть большая база данных, идут сложные вычисления,
конечно скорость и время становятся важными величинами.
|
|
Георгий |
Отправлено: 05.08.2003, 13:44 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Владимир
Признаю себя побеждённым — CreateThread в натуре работает быстрее, чем TThread
статистика с прилагающейся программы (все значения в tick):
CreateThread:
RunTime=2325671
LiveTime=2888392
TThread:
RunTime=5232580
LiveTime=5833822
Скоро этот алгоритм перенесу на QNX4.25 и посмотрю как там с многопоточностью...
|
|