| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > Время выполнения программы |
| Автор: Usya 20.2.2010, 22:32 | ||
Если утрировать, то задачу можно сформулировать следующим образом: есть прога для тестирования, в одном из обработчиков прописан следующий код:
Если заремить цикл, то время выполнения этого блока увеличивается в полтора-два раза (приблизительно с 8 с половиной до 14 с половиной минут). В чем может быть загвоздка? Буду признателен за любой совет. Заранее благодарен! P.s. Код программы не привожу, т.к. в ней более тысячи строк, а приводить код указанного обработчика без составных процедур не имеет смысла. |
| Автор: Alexeis 20.2.2010, 23:35 |
| Usya, цикл реально пустой? Или он все же влияет на работу алгоритма? |
| Автор: Usya 21.2.2010, 00:50 |
| Alexeis, artsb На самом деле в цикле должно что-то выполняться (и количество шагов в нем зависит от ряда факторов), но при поиске решения проблемы я просто взял и вместо моего цикла вставил пустой. Оказалось важно наличие цикла, а не то, что в нем. Причем его наличие почему-то влияет на время выполнения некоторых процедур, вызываемых в коде “бла-бла-бла”. Такое ощущение, что при вставке этого цикла на этапе компиляции Builder (6.0) умудряется что-то оптимизировать (возможно сам пытается что-то распараллелить из расчетов), в результате чего в среднем код работает быстрее. Кроме того, при попытке оптимизации ряда функций, я просто перестал понимать логику изменения времени выполнения программы. До этого момента все попытки оптимизации были как минимум адекватны изменению времени выполнения программы. Сейчас пытаюсь с этим разобраться. |
| Автор: Alexeis 21.2.2010, 01:04 |
| Usya, возможно приложение многопоточное и это как-то влияет на синхронизацию потоков ухудшая производительность. |
| Автор: Usya 21.2.2010, 01:21 |
| Alexeis, в данной программе я не использую распараллеливание процессов (только подключаюсь однократно к другому распараллеленному процессу для закачки данных для обработки, но это длится менее секунды). Возможно сам Builder пытается что-то намудрить с распараллеливанием, хотя все равно, как-то не совсем это понятно. |
| Автор: Alexeis 21.2.2010, 01:26 | ||
Нет, билдер такого не делает. В одном потоке невозможно распараллелится. |
| Автор: Usya 21.2.2010, 20:42 |
| Сегодня протестировал три варианта: 1-й – исходный, 2-й – поставил перед пустым циклом return, 3-й – заремил все, что находится после “бла-бла-бла”, включая цикл. Результаты в режиме Code Optimization = None: 17:42 17:37 15:36 В режиме Code Optimization = Speed: 9:01 8:44 13:33 Тестирование производилось параллельно по три экземпляра за проход (процессор четырехядерный – загружен по полной соответственно не был). Приведенное выше время выполнения указано только для кода “бла-бла-бла”. На разницу в секундах можно не обращать внимания (могут сказываться различные накладные расходы). Каждый из экземпляров прогнал дважды и усреднил (разница во времени выполнения однотипных экземпляров была от одной до тринадцати секунд, да и то - 13 сек только для одного из экземпляров, для остальных – не более семи секунд) – для статистики маловато, но чтобы оценить порядок времени выполнения каждого из экземпляров, возможно достаточно. Кстати, одна из возможных причин такого поведения описана в книге Криса Касперски “Техника оптимизации программ. Эффективное использование памяти” в параграфе “Проблема наведенных эффектов”, за что ему большое спасибо. А также спасибо всем отозвавшимся на решение этой задачки. P.s. Может я где-то и нахимичил с результатами тестов, но зато кое-что начало проясняться из нелогичности в оптимизации после прочитанного в книге, хотя читал слишком поверхностно. По ходу дела, с этим придется серьезно разбираться. |
| Автор: artsb 22.2.2010, 13:17 | ||||
Подозреваю, что вы неправильно тестировали. Небось использовали GetTickCount для расчёта времени работы кода (или подобные способы). Но это не правильно. Так нельзя получить правильных результатов. А дело тут в том, что Windows - это ОС с вытесняющей многозадачностью. Может получиться такая ситуация:
А нужно приблизительно так:
|
| Автор: Alexeis 22.2.2010, 14:05 |
| artsb>// в этом месте ОС может переключиться на другой поток. Usya>в данной программе я не использую распараллеливание процессов (только подключаюсь однократно к другому распараллеленному процессу для закачки данных для обработки, но это длится менее секунды) Так что такого происходить не может. Разве что в случае если машина загружена, но и тогда статистически за несколько запусков вариант без цикла был бы быстрее, а Usya утверждает что вариант без цикла всегда медленнее. Тут какой-то более хитрый случай. |
| Автор: artsb 22.2.2010, 14:33 |
Так я и не говорил про потоки одного процесса. Система может переключиться на любой поток. Возможно... А ещё может быть так, что ТС что-то не договаривает (как это часто бывает). Так что, скоро должен появиться пост: "Вот я ..., всё дело было в ...!" |
| Автор: Alexeis 22.2.2010, 15:28 | ||
все равно статистически результат был бы правильным, а Usya проводил много замеров. Мне видится использование внешней памяти (внешним устройствам) внутри кода, т.е. все же потоки используются, но неявно в ядре ОС. Кстати по твоему способу можно проводить замеры времени только в пользовательского режима, по идее это должно исключить время затраченное на ожидание чего-либо в режиме ядра (накладные вопросы синхронизации). |
| Автор: artsb 22.2.2010, 15:55 |
Результат был бы правильным ТОЛЬКО при условии, что код успел отработать за один квант времени, выделенный этому потоку. Об этом пишет Рихтер И он сам же написал, какие там были расхождения при использовании абсолютного одного и того же кода. |
| Автор: Usya 22.2.2010, 21:28 | ||||||||||
| Только с работы пришел и увидел, что тема на моем посте не закончилась. artsb
Я использовал clock() для замеров выполнения отдельных функций и циклов, и Now() (он остался у меня с момента начала написания проги) для замера выполнения полного времени тестирования, которое и привел прошлом посте. Я не буду спорить по поводу
Да и тесты проводились не в идеальных условиях и не с идеальными замерами, важно было следующее, что при наличии пустого цикла тестирование в режиме Code Optimization = Speed заканчивалось, в среднем, раза в полтора быстрее. Причем тестирование производилось далеко неоднократно и до того, как я начал тему и после, и проводилось при параллельном выполнении тестируемых экземпляров.
Все может быть.
Написал, чтобы оценить погрешность расчетов, и что эта погрешность не перекрывает разницы тестирования в минутах!!!
Спорный вопрос. Может я и не силен в оптимизации и приведу совсем левый пример, но у Криса Касперски рассматривается одна интересная задачка, когда одна и та же функция запускалась десять раз подряд. Время выполнения первого прогона почти вчетверо превышало последующие. Правда пример достаточно простой из нескольких строк. Но дело в другом - для идеального тестирования необходимо очищать все кэши и все буферы и т.д. и т.п. и дело здесь далеко не только в многозадачности Windows. Кстати, по поводу замеров времени в книге есть параграф "Неточность измерений", но это - отдельная тема. |
| Автор: xvr 26.2.2010, 16:48 |
| В моей практике бул случай, когда вставка в программу 1 NOP'а повышала быстродействие чуть ли не вдвое. (Правда это было давно и на SPARC платформе). Дело было в том, как разложился код программы в кэше кода из за выравнивания. |