процедура рисования линий - PullRequest
1 голос
/ 20 июля 2009

Как оптимизировать эту процедуру рисования линий? Будет ли работать memcpy быстрее?

void ScreenDriver::HorizontalLine(int wXStart, int wXEnd, int wYPos,
    COLORVAL Color, int wWidth)
{
    int iLen = wXEnd - wXStart + 1;

    if (iLen <= 0)
    {
        return;
    }
    while(wWidth-- > 0)
    {
        COLORVAL *Put = mpScanPointers[wYPos] + wXStart;
        int iLen1 = iLen;

        while(iLen1--)
        {
            *Put++ = Color;
        }
        wYPos++;
    }
}

Ответы [ 6 ]

4 голосов
/ 20 июля 2009

Я думаю, что вы хотите сказать "memset" вместо "memcpy". Замена этого бита кода:

while (iLen--)
{
    *Put++ = Color;
}

с

memset(Put, Color, iLen);

может быть быстрее, но многое зависит от вашего целевого процессора, архитектуры памяти и типичных значений iLen. Это вряд ли будет большой победой, но если у вас есть время, я призываю вас оценить альтернативы, так как подобные упражнения - единственный способ по-настоящему понять оптимизацию.

Конечно, это использование memset () будет работать, только если COLORVAL имеет размер символа.

1 голос
/ 21 июля 2009

Лучше всего, прежде чем делать что-либо еще, - использовать любые доступные инструменты профилирования низкого уровня. По крайней мере, получите общее время для здоровенного теста или 3. Без базового измерения вы снимаете в темноте. (Я должен знать, я виновен в этом, как и все остальные!)

Тем не менее, я отмечаю, что ваш код выглядит так, как будто имеет немало издержек на пиксель,

  1. Вызов memset () может быть выигрышным (если COLORVAL - sizeof (char)).

  2. С другой стороны, может помочь развертывание цикла - это сильно зависит от ваших входных данных, архитектуры машины и т. Д.

  3. Если ваше значение iLen разумно ограничено, вы можете рассмотреть возможность написания пользовательской функции для каждого полностью развернутого значения iLen (встроить первые несколько маленьких регистров в переключателе) и вызывать большие регистры через массив указателей на функции ,

  4. Самый быстрый вариант, конечно, обычно прибегнуть к сборке.

1 голос
/ 20 июля 2009

Нет, не совсем. memcpy копирует память, это чтение и запись, и вам не нужно читать. memset, который только пишет, записывает только байты, так что это тоже не сработает, если только COLORVAL не является байтом. Нет, оставьте все как есть, компилятор должен выдавать довольно хороший код. Не забывайте, что вы, вероятно, ограничены пропускной способностью памяти.

0 голосов
/ 23 июля 2009

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

Для линий, которые не расположены близко к горизонтали, может потребоваться больше времени на настройку таблицы указателей сканирования.

Честно говоря, для более реалистичных ситуаций, когда у вас есть не только цвета, но и ширины, стили линий и конечные стили, не говоря уже о режимах рисования, таких как XOR и псевдонимы, способ, которым я видел это, равен

  1. каждая «строка» на самом деле является заполнением полигонов, для которых есть довольно быстрые алгоритмы (что на самом деле и есть ваш алгоритм), и / или

  2. специальная процедура машинного языка генерируется на лету (хранится в стеке), потому что слишком много опций, чтобы иметь специальные подпрограммы для конкретных опций, и вы не хотите, чтобы алгоритм постоянно расспрашивать попиксельно, какие есть варианты.

0 голосов
/ 20 июля 2009

Один из самых быстрых способов нарисовать горизонтальную линию, или заполнить массив значением, в сборке - это использовать инструкции stosb, stosw, stosd. memset оптимизирован для использования stosb. Чтобы использовать значения dword, мы можем написать код, подобный приведенному ниже, чтобы нарисовать линию,

__asm {
        cld
        mov eax, color
        mov ecx, screen_width
        mov edi, video_buffer
        rep stosd
}

Но я вполне уверен, что ваш внутренний цикл while будет оптимизирован компилятором для использования stosd в любом случае.

0 голосов
/ 20 июля 2009

По личному опыту я обнаружил, что memcpy немного быстрее, чем прямой доступ с указателем ... но лишь немного, обычно это не новаторская оптимизация.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...