Конференция "Игры" » Быстрый канвас [Delphi, Windows, ХР]
 
  • Pavia © (16.03.09 15:37) [100]

    > А у меня вариант Pavia быстрее, причём весьма прилично,
    > почти в 2 раза.

    У меня тоже прерирост но только в 1.33. И Эта цифра тем  больше чем больше разрешение изоброжения. Я предпочитаю тестировать на 1024х1024.

    Можно такой код попробовать. Он дал еще прирост еще на 10% процентов по сравнению с Draw2_5.

    Ище в коде добавил Bitmap.Free; от утечек памяти. И то они тестирование сбивают.

    Procedure Draw2_6;
    Var x, x3, y, dx : Integer; Bitmap: TBitmap; Pixels: PByteArray;
    Begin
    Bitmap:=TBitmap.Create;
    Bitmap.PixelFormat:=pf24bit;
    Bitmap.Width:=640;
    Bitmap.Height:=480;
    dx:=DWord(Bitmap.ScanLine[1])-DWord(Bitmap.ScanLine[0]);
    Pixels:=Bitmap.ScanLine[0];
    For y:=0 To Bitmap.Height-1 Do
    Begin
     x:=Bitmap.Width-1;
     repeat
      Pixels[x*3+0]:=y+y;
      Pixels[x*3+1]:=x+y;
      Pixels[x*3+2]:=x+x;
      dec(x);
     until x<=0;
    Inc(DWord(Pixels), dx);
    End;
    Form1.Canvas.Draw(0, 0, Bitmap);
    Bitmap.Free;
    End;



     x:=Bitmap.Width-1;  Вызов объекта сбивает оптимизатор дельфи.
    Лучше завести переменную Width:=Bitmap.Width-1 и ее использовать.
  • DomiNickDark (17.03.09 11:53) [101]
    Думаю скорость ещё и от самой машины зависит...
    Вот на моей машине "Вариант № 2_6" чуть быстрее "Варианта № 2"...

    > Ище в коде добавил Bitmap.Free; от утечек памяти. И то они тестирование сбивают.

    Да... Это я как-то маху дал... :(
    Я просто обычно использую тока один Bitmap: При создании формы создаю Bitmap, а уже при закритии программы уничтожаю его...

    > x:=Bitmap.Width-1;  Вызов объекта сбивает оптимизатор дельфи.
    > Лучше завести переменную Width:=Bitmap.Width-1 и ее использовать.


    Мда..? Не знал... А чем это объясняется? :)

    > > Про спец ключи я знаю...
    > Тогда мне не понятна проблема. :)


    Проблема проста - предпросмотр СкринСейвера не работает.....
  • @!!ex © (17.03.09 11:57) [102]
    > > > Про спец ключи я знаю...
    > > Тогда мне не понятна проблема. :)
    >
    > Проблема проста - предпросмотр СкринСейвера не работает.....

    О ключе вы знаете. Хэндл есть.
    Почему не работает?
  • Sapersky (17.03.09 15:55) [103]
    У меня тоже прерирост но только в 1.33.

    Сейчас проверил на другом компе - 1.23. Видимо, в 1-ом случае повлияла Win98, наверное, какие-то системные функции там выполняются медленнее.

    Можно такой код попробовать. Он дал еще прирост еще на 10% процентов по сравнению с Draw2_5.

    Более удачное распределение переменных по регистрам получилось. В первом варианте счётчик цикла был на стеке, во втором - в регистре.

    x:=Bitmap.Width-1;  Вызов объекта сбивает оптимизатор дельфи.
    Лучше завести переменную Width:=Bitmap.Width-1 и ее использовать.


    Но в приведённом примере разницы почему-то нет :)
    Скорее, вреден вызов функции (GetWidth), но он делается один раз на скан-линию, так что это не принципиально.
    А если без вызова - в худшем случае 2 mov (получаем адрес объекта + получаем свойство) супротив одного. Во внутреннем цикле может иметь значение, и то небольшое.
  • Дуб © (17.03.09 16:54) [104]
    А, а все-таки бы тогда при таких раскладах и статью почитать можно было бы.

    Брюзжу, да.
  • Вася (17.03.09 20:37) [105]
    DomiNickDark, Pavia, Спасибо)
    А как ещё ускорить можно не знаете? ;)
  • MBo © (18.03.09 09:13) [106]
    >А как ещё ускорить можно не знаете? ;)
    А зачем?
  • Pavia © (18.03.09 17:44) [107]

    > А как ещё ускорить можно не знаете? ;)

    Знаем. Можно сделать раскрутку цикла. еще 28% процентов прироста

    Procedure Draw2_7;
    Var x, x3, y, dx,xx,yy : Integer; Bitmap: TBitmap; Pixels: PByteArray;
    Begin
    Bitmap:=TBitmap.Create;
    Bitmap.PixelFormat:=pf32bit; // Быстрее заработало.
    Bitmap.Width:=SWidth; // Просто константы тестировать удобнее
    Bitmap.Height:=SHeight;
    dx:=DWord(Bitmap.ScanLine[1])-DWord(Bitmap.ScanLine[0]);
    Pixels:=Bitmap.ScanLine[0];
    For y:=0 To Bitmap.Height-1 Do
    Begin
     yy:=y+y; // Вынес из цикла
     x:=Bitmap.Width-4;
     repeat
      xx:=x+x;
      Pixels[x*4+0]:=yy;
      Pixels[x*4+4]:=yy;
      Pixels[x*4+8]:=yy;
      Pixels[x*4+12]:=yy;
      Pixels[x*4+2]:=xx;
      Pixels[x*4+6]:=xx+2;
      Pixels[x*4+10]:=xx+6;
      Pixels[x*4+14]:=xx+8;
      Pixels[x*4+1]:=x+y;
      Pixels[x*4+5]:=x+y+1;
      Pixels[x*4+9]:=x+y+2;
      Pixels[x*4+13]:=x+y+3;
      dec(x,4);
     until x<=0;
    Inc(DWord(Pixels), dx);
    End;
    Form1.Canvas.Draw(0, 0, Bitmap);
    Bitmap.Free;
    End;


    У меня процедура выполняется со средней скоростью 14тик на пиксель. Что неплохо.
    Дальше еще можно задействовать многоядерность и перейти к ассемблеру и воспользоваться sse.
  • Pavia © (18.03.09 18:29) [108]
    Из этих 14 тиков 5 уходит на очистку при создании и 5 при копировании через Draw.
  • DomiNickDark (18.03.09 20:36) [109]
    > Знаем. Можно сделать раскрутку цикла. еще 28% процентов прироста

    Ого...
    Pavia, да Вы спец...
    Вы, случайно, не увлекаетесь ДемоСценами? :)

    > Дальше еще можно задействовать многоядерность и перейти
    > к ассемблеру и воспользоваться sse.


    Я и до "2_7" навряд ли бы додумался, а ещё "дальше" мне будет "рановатто"...
    "Учиться, учиться и учиться..."

    + в моей подборке литературы по программированию не нашлось даже похожих по названиям разделов... :(

    Можете посоветовать проверенные книги для дальнейшей оптимизации и ускорения..?
    На будущее..... :)
  • antonn © (19.03.09 00:17) [110]

    > Дальше еще можно задействовать многоядерность

    имхо, накладные расходы все перекроют, поможет если изображения огромные, в разных потоках поочередно рисовать.
  • Pavia © (19.03.09 01:40) [111]

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

    А если так. Напримере двух ядер. Первый поток рисует четные строчки второй нечетные?
    Потоки не перекрываются задачу распаралелили. Наклодные рассходы минимальны, при правельной организации памяти. Или первый кадр ресует один поток второй кадр другой поток. Подготовка данных идет тоже в два потока в два разных буфера.
    Обработка изоброжений давно уже удачно паралелится. Да и редеринг тоже пробуют и говорят весьма удачно.
  • Б (19.03.09 16:12) [112]
    > А как ещё ускорить можно не знаете? ;)

    Сдвиговые операции самые быстрые.
    Воспользоваться готовыми таблицами.
    Развёртка циклов - хороший способ оптимизации.
    Воспользоваться Ассемблером.
    Загнать рисунок в массив и работать потом с ним.
    Работать с растром через указатель - напрямую и т.д.

    > Pavia [107]
    Локальные переменные можно и неудалять, процедура на выходе, сделает это за нас.
    Лучше умножить x на 4 один раз, вместо 12.
  • Pavia © (19.03.09 16:27) [113]

    > Локальные переменные можно и неудалять, процедура на выходе,
    >  сделает это за нас. Лучше умножить x на 4 один раз, вместо
    > 12.

    Память под объекты выделяется в куче поэтому компилятер не очещает памить за ними. Нужно делать ручками.
    А вот x*4 компилятор считает один раз вместо 12.
  • DomiNickDark (19.03.09 22:18) [114]
    Хм... Терминов "раскрутка цикла" и "развёртка цикла" раньше не встречал... Про их где-нибудь пишут в книгах?

    При тестировании (на 1024х1024) сбоку слева недорисовывалась часть битмапа... Белая полоска получалась...
    Поменял "until x<=0;" на "until x<0;" - стало нормально... :)

    И ещё чуть коэффициенты чуть подправил:

    Pixels[x*4+6]:=xx+2;
    Pixels[x*4+10]:=xx+4;
    Pixels[x*4+14]:=xx+6;



    И ещё нужно бы сказать, что выносить из цикла "yy:=y+y;" выгодно только для конкретного примера "RGB(x+x, x+y, y+y);"...
    Так, на всякий... :)

    Пробовал сразу по 8 пикселов в цикле считать... Еле заметно ускорилось...
    Тогда я что-то так обрадывался и сделал сразу по 16 - получилось почему-то наоборот в два раза медленнее... :(
    Есть ли способы рассчитать оптимальное количество..? Или тока мерять на практике можно?
  • Pavia © (20.03.09 04:08) [115]

    > Хм... Терминов "раскрутка цикла" и "развёртка цикла" раньше
    > не встречал... Про их где-нибудь пишут в книгах?

    Руководства по оптимизации от интел и амд подойдут?


    > Пробовал сразу по 8 пикселов в цикле считать... Еле заметно
    > ускорилось...

    На моем процессоре придел достигнут 4.5тика.  1 тик на вычисление 0.5 на запись 3 байта 1.5*3=4.5 Остается мало вариантов для оптимизации только SSE и MMX. снизить число записей до 1 на два пикселя и совместить запись с рассчетами. А это уже прямая дорога в ассемблер.

    Число портов для вычислений около 4 и еще 1 для записи чтения. Поэтому больше 4 не делают. 4 это рекоминдованное число.  Хотя порой бывают разные эффекты, так что практика иногда и расходится с теорией.
  • hotspot (20.03.09 11:13) [116]
    Извините что чуть в сторону от темы, но ближе ничего пока не нашел..
    Надо нарисовать порядка 10000 окружностей. TCanvas делает это (в зависимости от размера окружности) за 0,6 - 1,5 секунды. Можно ли вывод осужествить быстрее?
    А то CAD, который секунду пытается прорисовать изображение при любом изменении объекта - эт перебор :(
  • ЮЮ © (20.03.09 11:56) [117]

    > Можно ли вывод осушествить быстрее?

    Можно, если все 10000 окружностей не изменяют свое положение. Окружности, не перемещаемые в данный момент пользователем, должны быть просто фоном, а объектами становиться только когда с ними взаимодействуют.

    Могу выслать небольшой проект 5-ти летней давности с подобной функциональностью.
  • hotspot (20.03.09 12:08) [118]
    Буду очень благодарен. hotspot2006(собака)ya.ru
  • @!!ex © (20.03.09 13:30) [119]
    > [116] hotspot   (20.03.09 11:13)

    редкий CAD рисует софтверно.
 
Конференция "Игры" » Быстрый канвас [Delphi, Windows, ХР]
Есть новые Нет новых   [118241   +25][b:0.001][p:0.002]