КГ_8глава (Компьютерная графика), страница 2
Описание файла
Файл "КГ_8глава" внутри архива находится в папке "Компьютерная графика". Документ из архива "Компьютерная графика", который расположен в категории "". Всё это находится в предмете "инженерная графика" из 4 семестр, которые можно найти в файловом архиве РТУ МИРЭА. Не смотря на прямую связь этого архива с РТУ МИРЭА, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "компьютерная графика" в общих файлах.
Онлайн просмотр документа "КГ_8глава"
Текст 2 страницы из документа "КГ_8глава"
1. Временно исключить можно не любую операцию, а только ту, отсутствие которой не нарушает логику работы программы. Другие операции должны выполняться в полном объеме и в той же последовательности. Это главное условие. Остальные условия можно сформулировать как следствие.
2. Необходимо быть внимательными, если вы работаете с оптимизирующим компилятором. Он может сделать такие изменения в программе во время компиляции, о которых мы и не подозреваем. Мы можем исключить одну операцию — а компилятор исключит еще несколько и никак нам об этом не сообщит. Это приведет к иллюзии значительной роли временно исключенной операции.
3. Нельзя изменять стратегию использования виртуальной памяти (если это специально не анализируется). Например, в функции DrawstudyExampie нами не используется ни одна из файловых операций. Однако в ходе выполнения этой функции, программа может часто обращаться к диску. Это может быть в случаях, когда открываются значительные по объему массивы, и операционная система делает перераспределение виртуальной памяти между оперативной памятью (RAM) и диском. А в данное время мы временно выключили эту операцию, и обращения к диску прекратились — это может быть свидетельством того, что отныне все массивы целиком размещаются в RAM. Последнее может привести к ускорению выполнения программы, поскольку обращение к RAM осуществляется намного быстрее, чем к диску. Кроме того, когда размера RAM недостаточно для полной программы, то даже уменьшение объема кода при исключении может привести к тому, что программа будет работать быстрее — так как отныне все размещается в RAM. Однако в этом случае уменьшения времени не пропорционально времени выполнения исключенной функции, и это не позволит рассчитать ее вклад в общее время выполнения программы. Таким образом, необходимо пользоваться правилом: объем оперативной памяти должен быть достаточным как для полной программы, так и программы с исключением.
Способ временного исключения отдельных операций можно трактовать так: если после исключения некоторой операции время выполнения программы уменьшается не существенно, то эту операцию не нужно оптимизировать в первую очередь. Однако если в результате анализа мы и обнаружим некоторую длительную операцию, то это еще не означает, что ее можно ускорить.
Продолжим дальше анализ программы. Временно выключить функцию MyPoiygon нельзя, поскольку тогда будет рисоваться только шар, а это означает другой порядок заполнения пикселами Z-буфера и растра битмапа двойного буфера. По аналогичной причине нельзя временно выключить функцию
Sphere: : Draw (HDC hdc). А ЧТО же ТОГДа МОЖНО?
Рассмотрим функцию SetPixMyz. Если ее исключить, то прекратится запись пикселов в оба растра — Z-буфера и растра битмапа. Однако те функции, ко-
торые остались, выполняются так же, как и до исключения. Временно ш ключим setPixMyz. Результат— 57.5. То есть, из 807 секунд почти все врем расходуется на запись пикселов.
Составная часть функции SetPixMyz — вызовы функции SetPixel. Времен^ исключим ее. Результат— 70 секунд. Результаты временных исключен^ отобразим следующей диаграммой (рис. 8.3).
Рис. 8.3. Диаграмма исключения операций
По диаграмме исключения можно рассчитать, сколько времени расходуется» программе на выполнение отдельных операций:
Время выполнения функции SetPixel:
Необходимо учитывать, что функция SetPixel — вложенная по отношению |
К SetPixMyz.
поэтому целесообразно будет для анализа SetPixMyZ рассматривать долю времени, не относящегося к вызову setPixei:
Таким образом, мы уже можем рассмотреть результаты измерений для некоторых отдельных операций:
Этот перечень неполон, можно анализировать еще некоторые функции, однако уже ясно, что основная причина низкой скорости — это использование функции setpixei. Ее мы никак не можем изменить, ибо это функция API Windows. Но можно попробовать обойтись без нее.
Один из способов работы с растром — непосредственный доступ к памяти, хранящей растровый массив. Такой способ достаточно известен. Он использовался при разработке почти всех быстрых графических программ для когда-то популярной операционной среды MS-DOS. Среди функций MS-DOS предусмотрена функция рисования пиксела на экране, но она работала так же медленно, как и функция API Windows SetPixei. Поэтому для создания изображений на экране часто использовались операции непосредственной записи в видеопамять. В операционной системе Windows обращение прикладных программ к видеопамяти запрещено, а вся растровая графика основывается на понятии контекста графического устройства. Через контекст мы рисуем на экране, через контекст— в растрах битмапов. Кажется, это и все. Однако разработчики Windows предусмотрели еще одну возможность работы с растрами — операции с растрами в формате DIB (Device Independent Bitmap).
Можно создавать растр, не привязанный к какому-то графическому устройству по формату пикселов, а самое главное — предусмотрен доступ к растру по указателю на массив в памяти. С этим массивом можно производить любые операции, поскольку становится известным его адрес в виртуальной памяти. В том числе и выполнять операции над отдельными байтами и битами,; которые представляют пикселы растра. Это открывает широкие возможности для создания собственных графических библиотек. Текст программы studex35. срр:
В программе использована одна из функций API Windows для работы с растрами DIB. Это функция stretchDiBits, которая осуществляет вывод растра из памяти по адресу pRastBuf в определенный контекст. Растровый буфер DIB здесь в формате 24-битного цвета— это позволяет достаточно просто моделировать различные интенсивности отражения света для цветных объектов. Для корректности сравнения работы обеих программ (studex34,35) все испытания следует производить в видеорежиме True Color 24 бит на пиксел.
В 24-битном режиме цвет каждого пиксела определяется тройкой байтов RGB. Как раз эти байты и записываются в память функцией setPixRastrMem.
Скомпилируйте и проверьте работу программы studex35. Полный оборот камеры в ней делается за 88 секунд в отличие от studex34, где полный оборот составлял 807 секунды. Таким образом, создание одного кадра выполняется в среднем за 88/361 = 0.24 секунды. Благодаря замене функции SetPixel нашей собственной функцией SetPixRastrMem достигнуто уменьшение времени рендеринга более, чем в 9 раз. И это несмотря на то, что функция stretchDiBits работает медленнее, чем BitBit.
Необходимо отметить, что функция SetPixRastrMem предназначена только для 24-битных растров, a SetPixel корректно работает во всех цветовых форматах, поэтому она и работает медленнее.
8.2. И снова анализ
и оптимизация программы
Проанализируем теперь программу studex35. Для нее диаграмма исключения операций имеет следующий вид (рис. 8.4).
Рис. 8.4. Диаграмма исключения операций studex35
Как мы видим, операции записи пикселов в растр DIB составляют уже небольшую часть общего цикла рисования. Также уменьшилась доля времени для записи всех пикселов (setPixMyz). Необходимо проанализировать другие операции.
Ранее, в ходе анализа программы studex34, мы отмечали, что нельзя временно исключать операцию MyPolygon, так как изменится логика заполнения
Z-буфера — кроме полигонов в нашей программе рисуется и шар. И все же давайте сделаем отдельный анализ для цикла вывода многогранников, исключив На весь период измерений функцию Sphere: : Draw. ПОНЯТНО, ЧТО без
шара процесс создания изображения будет проистекать по-другому. Однако мы вынуждены пойти на это— когда сложно анализировать весь процесс в целом, необходимо попробовать разделить его на более простые составляющие.
Снова воспользуемся методом временного исключения. Замеры времени отражены на следующей диаграмме исключения для многогранников (рис. 8.5).
Рис. 8.5. Операции вывода многогранников Определим общее время, затрачиваемое для работы функций:
Глядя на эти цифры, можно предположить, что необходимо оптимизировать функцию MyPoiygon, которая вносит наибольший вклад в общее время. Однако, для того чтобы выяснить, как именно ее оптимизировать, следует проанализировать структуру программы, а точнее— иерархию вложенных функций. Вложенной функцией мы будем для краткости называть функцию, которая вызывается в теле другой функции. Таким образом, общее время работы
некоторой функции складывается из вызовов вложенных функций (если они есть) плюс время работы операторов собственно этой функции
Для анализа каждой функции будем в первую очередь оценивать время собственной работы, а не время работы вложенных функций. Это время, очевидно, равно
На рис. 8.6 изображена иерархия вложенности функций studex35.
Рис. 8.6. Вложенность функций
Из этой схемы видно, что собственное время работы функции MyPolygon составляет разность между общим временем работы этой функции и временем работы функций Ref lectionColQE..H MyLineHor: ----
Для остальных функций собственное время составит
Обратим внимание на эти цифры. Подозрительно много времени занимают операции тела функции MyLineHor. Возможно, ее следует оптимизировать в первую очередь. Следующим в этом списке фигурирует тело функции setPixMyz— 15 сек. Собственное время работы операторов тела функции MyPolygon относительно невелико.
План оптимизации программы может быть таким:
1. Совершенствование функции MyLineHor.
2. Уменьшение количества уровней вложения функций— можно сэкономить время, которое расходуется на вызовы вложенных функций и пере-
дачу им значений аргументов. Для этого код функции setPixRastrMai расположим непосредственно в теле функции setPixMyz. Отдельная функ-? ция SetPixRastrMem нам уже не нужна.