#c #optimization #buffer
#c #оптимизация #буфер
Вопрос:
У меня есть colorBuffer Color[width*height]
(скорее всего, 800 * 600)
и во время растеризации я вызываю:
void setPixel(int x, int y, Color amp; color)
{
colorBuffer[y * width x] = color;
}
Оказывается, что этот произвольный доступ к цветовому буферу действительно неэффективен и замедляет работу моего приложения.
Я думаю, что это вызвано тем, как я его использую. Я вычисляю некоторый пиксель (с помощью алгоритмов растеризации) и вызываю SetPixel.
Поэтому я думаю, что мой буфер не находится в кэше, и это основная проблема. При попытке записи во весь буфер сразу, это намного быстрее.
Есть ли какой-нибудь способ, как это оптимизировать?
Редактировать
Я не использую его для заполнения буфера двумя циклами for.
Я использую его для рисования «случайных» пикселей.
например, когда я растеризую строку, я использую ее как
setPixel(10,10);
calculate next point
setPixel(10,11);
calculate next point
setPixel(next point)
...
Комментарии:
1. Создание его встроенным также может немного замедлить работу
Ответ №1:
На мой взгляд, шаблон доступа к буферу зависит от порядка, в котором ваш алгоритм обрабатывает пиксели. Разве вы не можете просто изменить этот порядок, чтобы он создавал схему последовательного доступа к вашему буферу?
Комментарии:
1. По крайней мере, можете ли вы отсортировать объекты для растрирования в порядке сверху вниз, слева направо, а затем растрировать каждый объект, работающий в одном направлении?
2. @Бесполезно нет, я не могу. Я должен растеризировать их, как только получу.
3. Почему имеет значение, растеризуете ли вы «с нетерпением» (т. Е. Сразу после вызова), если все сделано до следующего обновления дисплея, сохранения в файл или чего-то еще? Если это так, все, что вы можете сделать
setPixel
, это попробовать встроить и попытаться сделатьColor
объект как можно меньше.
Ответ №2:
Да, вы должны стараться работать с кэшем, но первое, что я бы сделал, это выяснить, что требует времени.
Это достаточно просто. Просто приостановите его несколько раз и посмотрите, что он делает.
Если он в основном calculate next point
включен, вы должны посмотреть, что он там делает, потому что на это уходит время. (Я полагаю, вы понимаете, что под «в» я подразумеваю «в стеке».)
Если он в основном SetPixel
включен, когда вы приостанавливаете его, посмотрите на окно разборки.
Если он тратит много времени на пролог / эпилог процедуры, он должен быть встроен.
Если он тратит много времени на фактическую инструкцию перемещения colorBuffer
, то вы сталкиваетесь с проблемой кэша.
Если он тратит много времени в коде на вычисление индекса y * width x
, то вы можете захотеть посмотреть, можете ли вы каким-то образом использовать инициализированный указатель, который вы выполняете.
Если вы что-то исправите, вам следует сделать все это снова, потому что вы, возможно, обнаружили еще одну возможность ускорить процесс.
Комментарии:
1. Спасибо. Это проблема с кэшем. Основная проблема заключается в том, как сделать это быстрее. Возможно, заставить буфер оставаться в кэше или что-то в этом роде
Ответ №3:
Первое, на что следует обратить внимание, это то, что способ обработки пикселей имеет огромное значение для скорости. Если вы сделаете
for (int x = 0; x < width; x)
{
for (int y = 0; y < height; y)
{
setPixel(x,y,Color());
}
}
это будет очень плохо для производительности, потому что вы буквально прыгаете по ширине памяти (обратите внимание, что вы делаете y * width x).
Если вы просто измените порядок обработки на
for (int y = 0; y < height; y)
{
for (int x = 0; x < width; x)
{
setPixel(x,y,Color());
}
}
вы уже должны заметить прирост производительности, поскольку процессор теперь получает возможность кэшировать обращения к памяти (чего раньше не было).
Кроме того, вы должны проверить, можете ли вы определить, что целые блоки пикселей будут иметь одинаковое значение цвета, прежде чем фактически устанавливать память. Затем вы можете скопировать эти постоянные значения цвета по блокам в свой массив изображений, что также может сэкономить вам значительную производительность.
Комментарии:
1. @relaxxx Ну, я полагаю, вы вычисляете объекты в цикле? Вместо определения положения для каждого цвета было бы намного эффективнее, если бы вы сканировали буфер с помощью двух вложенных циклов и для каждой позиции пикселя определяли цвет.
2. Я не могу сделать это так. Пользователь может использовать его как
setColor
, аpaintCircle
затем ещеsetColor
и ещеprintLine
. Я вычисляю точки окружности и записываю их фактическим цветом. затем вычислите точки линии и вычислите их с новым фактическим цветом. Я действительно не вижу способа, как впоследствии заполнить цветной буфер3. @relaxxx Ну, ты можешь. Вот как работают растеризаторы. Смотрите, например: en.wikipedia.org/wiki/Scanline_rendering , cs.uu.nl/docs/vakken/gr/resources/08-triangles.slides.pdf