Войти
ПрограммированиеФорумГрафика

Оптимизация. Как еще улучшить внутренние циклы? Масштабирование CSR-спрайтов

Страницы: 1 2 315 16 Следующая »
#0
(Правка: 27 сен 2022, 0:51) 21:05, 24 сен 2022

  Есть такой код:

+ Показать

  Делает масштабирование непрозрачных пикселей CSR-спрайта, но не суть. Вопрос в том, можно ли еще как-то оптимизировать внутренние циклы? Например, избавиться от взятия целых частей или еще какие-то трюки?

#1
21:23, 24 сен 2022

https://stackoverflow.com/questions/18971401/sparse-array-compres… ing-simd-avx2

#2
21:37, 24 сен 2022

  Не совсем то. Там какая-то магия интринсиков, недоступная в компиляторе FreePascal. К тому же компрессия у меня и так уже есть. Хотелось бы еще как-то ускорить именно уже вывод масштабированного спрайта в пределах высокоуровневой оптимизиации и без SIMD(ну и без асм-вставок разумеется). А потом, если предел будет достигнут, буду думать о многопоточке.

#3
21:44, 24 сен 2022

посмотрю попозже. Может найду что.

#4
21:48, 24 сен 2022

  Было бы неплохо;)

#5
21:55, 24 сен 2022

Что это за образец говнокода?
16 if, 5 else, goto
Максимально нечитаемые переменные, такое ощущение, что у меня дислексия.
bmp_ftimg_height-nt_pix_arr_row_mrg_top-nt_pix_arr_row_mrg_btm-1 do
nt_pix_r,nt_pix_g,nt_pix_b,bg_pix_r,bg_pix_g,bg_pix_b   

Какие-то странные конструкции, понятные только одному автору.
bmp_bkgnd_ptr2+00000000000000000
@bmp_bkgnd_ptr      [000000000000000000000000000000000000000000000000000000000000000000000]

Я не совсем уверен для чего ты привёл этот код и кто в нём должен разбираться =/

#6
22:06, 24 сен 2022

  Kripto289, то есть Вас смутила эстетическая сторона кода, которая ни на что не влияет, но по теме высказать нечего? Ясно). К тому же, насчет идентификаторов, неудивительно было бы слышать претензии от человека, который никогда не программировал графику, а те, кто варятся в данной области уже и так примерно поняли смысл. Например, "bmp" от bitmap, "bkgnd" от background и т.д. Тем более я специально закомментировал во внутренних циклах участки кода, чтобы понимать хоть примерно, что и откуда берется.
  P.S. Столько if и одно goto там не просто так, если что.

#7
22:33, 24 сен 2022

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


ArtProg
> К тому же, насчет идентификаторов, неудивительно было бы слышать претензии от
> человека, который никогда не программировал графику
Обожаю когда в споре придумывают аргумент из ничего, вообще ничем не подкрепляя. Особенно это смешно читать, зная что я уже лет 7 пишу шейдера/код и мой основной профиль в геймдеве - графика.
Может быть как раз поэтому у меня претензии к неймингу?

ArtProg
> а те, кто варятся в данной области уже и так примерно поняли смысл. Например,
> "bmp" от bitmap, "bkgnd" от background и т.д
А оно мне надо?
Я вижу подобную строчку
nt_pix_r,nt_pix_g,nt_pix_b,bg_pix_r,bg_pix_g,bg_pix_b 
bmp_ftimg_height-nt_pix_arr_row_mrg_top-nt_pix_arr_row_mrg_btm
и должен потратить минуту на то, что бы расшифровать твои ребусы. У тебя платные нажатия клавиш?
А это что такое?
[000000000000000000000000000000000000000000000000000000000000000000000]
Ты на клавишах уснул или что это?

 if ((scl_mul.x<0.2)         and
          (scl_mul.y<0.2))         or
         ((scl_mul.x>0.5-0.01)    and
          (scl_mul.x<0.5+0.01)    and
          (scl_mul.y>0.5-0.01)    and
          (scl_mul.y<0.5+0.01))    or
         ((scl_mul.x>0.5-0.01)    and
          (scl_mul.x<0.5+0.01)    and
          (scl_mul.y>1.0-0.01)    and
          (scl_mul.y<1.0+0.01))    or
         ((scl_mul.x>0.5-0.01)    and
          (scl_mul.x<0.5+0.01)    and
          (scl_mul.y>1.0-0.01)    and
          (scl_mul.y<1.0+0.01))  then

Подобный ужас это классика говнокода.
Просто прими факт, что твой код ужасен даже для начинающего программиста, а уж показывать такой ужас и просить кого-то его оптимизировать - это неуважение к читателю. И он имеет полное право не согласиться с тем, что бы читать и разбираться в этом ужасе.

#8
23:13, 24 сен 2022

  Добавил некоторые обозначения в первом посте под спойлером. Надеюсь стало понятнее.

#9
23:41, 24 сен 2022

Пока смотрю код, несколько замечаний (если ты готов принять их).

1 - удаляй все не значащие нули.
2 - найди более подходящий способ структуризации кода (я сейчас просматриваю и понимаю, что ты в нём далеко не совсем разобрался).
  когда код будет более структурирован, ты увидишь несколько повторяющихся блоков кода. часть из них можно будет удалить.
3 - постарайся вычисления делать сразу (0.5 + 0.01 и подобные). FPC зачастую может ни как не оптимизировать числа, особенно с плавающей запятой (для Linux там вообще бардак).

#10
(Правка: 23:57) 23:53, 24 сен 2022

  Спасибо за замечания. Немного обьясню почему сделано так, а не по-другому. Вынести-то повторяюшиеся блоки кода можно, но это так или иначе либо вобще на производитеьности не скажется либо еще больше все просядет в этом плане. Даже не стал использовать функции RGB и подобные.
  Ну и за предрасчет констант. Они ж вроде не во внутреннем цикле находятся, поэтому на вычисления слабо влияют. Ведь не зря в названии темы написано о рассмотрении именно внутренних циклов.
  Меня больше беспокоит, что можно сделать, например, с вот этим и подобными блоками

s1_            :=Trunc(alpha_inv_mul_s10000*s1);
bg_pix_r       :=Byte(bmp_bkgnd_ptr2^>>00);
bg_pix_g       :=Byte(bmp_bkgnd_ptr2^>>08);
bg_pix_b       :=Byte(bmp_bkgnd_ptr2^>>16);
bmp_bkgnd_ptr2^:=((bg_pix_r+(s1_*(nt_pix_r-bg_pix_r))>>16)<<00+
                  (bg_pix_g+(s1_*(nt_pix_g-bg_pix_g))>>16)<<08+
                  (bg_pix_b+(s1_*(nt_pix_b-bg_pix_b))>>16)<<16);

По замерам они составляют львиную долю потребления ресурсов. Может быть удастся обойтись без целой части или еще больше упростить выражения со сдвигами?

#11
0:33, 25 сен 2022

ArtProg
> Меня больше беспокоит, что можно сделать, например, с вот этим и подобными
> блоками
Для чего вообще такое используется? По описанию вообще не понятно для чего ты используешь CSR формат матриц, почему это у тебя называется спрайт, и почему надо масштабировать именно непрозрачные пиксели.
Отмотай в самое начало, может ты вообще делаешь что-то не то? Ну типо нафига хранить спрайты в виде матриц, а не форматов GPU или изображений? От этого есть какой-то профит, кроме усложнения кода? Почему для масштабирования не использовать шейдера, которые для этого и созданы?
В общем, одни вопросы.

#12
(Правка: 1:48) 1:17, 25 сен 2022

Kripto289
  >Для чего вообще такое используется? По описанию вообще не понятно для чего ты используешь CSR
  Отрисовка спрайтов, где количество полностью прозрачных пикселей больше некоторого значения(теоретически больше одной трети от всего изображения, но на практике это число несколько меньше), карты тайлов, отрисовка очень большого количества линий с практически мгновенным выделением требуемых точек без перерисовки всего сплайна, бесплатный контурный анти-алиасинг, прорисовка сотен тысяч статических спрайтов при статической камере с разными слоями параллакса(между каждым слоем могут двигаться, возможно анимированные, спрайты других слоев с иными значениями параллакса). Это только те применения, что мне удалось сходу вспомнить. Каждая из этих техник достаточно сложна в реализации. Поэтому не вижу особого смысла рассказывать о них(как-нибудь напишу статью, кому будет интересно могут почитать).
  >и почему надо масштабировать именно непрозрачные пиксели.
  Потому что таким образом идет пропуск кучи ненужных проверок(Вы же не будете надеюсь утверждать, что, например, 100 проверок на непрозрачность более эффективна, чем всего один инкремент указателя), а если рассматривать еще и аффинные преобразования вроде масштабирования и поворота, то накладные расходы в разы больше.
  >Для чего вообще такое используется? По описанию вообще не понятно для чего ты используешь CSR
  Видеокарта просто тупо молотит каждый пиксель в независимости от надобности проверок на прозрачность, то есть тупым брутфорсом, но выигрывает только за счет количества потоков, но это еще не значит, что она использует имеющиеся алгоритмы максимально эффективно. Мне же интересен именно максимально эффективный алгоритм. Если он будет работать предельно быстро на CPU в однопотоке, то при должной сноровке может быть перенесен и на GPU.
  >От этого есть какой-то профит, кроме усложнения кода?
  Соглашусь насчет усложнения. Но назовите три ключевые характеристики такие как гибкость кода, производительность и понятность и вычеркните что-то одно. Вот и получите принцип работы любого кода. Поэтому да, быстрый код не всегда красивый. Но это факт, который трудно оспорить.
  >Почему для масштабирования не использовать шейдера, которые для этого и созданы?
  Что Вы понимаете под шейдером? К примеру, код выше похож на шейдер?

#13
1:24, 25 сен 2022

ArtProg
> for y:=0 to bmp_ftimg_height-nt_pix_arr_row_mrg_top-nt_pix_arr_row_mrg_btm-1 do
выносим в самое начало:

yend := bmp_ftimg_height - nt_pix_arr_row_mrg_top - nt_pix_arr_row_mrg_btm - 1;

визуально лучше выглядит (и более понятно):

for y := 0 to yend do

Дальше можно оптимизировать выкинув "статические" данные из циклов:
ArtProg
> v1 :=((scl_mul_x*(nt_pix_intr_sht_arr_ptr^+bmp_ftimg_left)+d1_)>>16);
> v2 :=((scl_mul_y*(nt_pix_arr_row_mrg_top+y+bmp_ftimg_top )+d2_)>>16);
создать массивы с данными по X и  по Y и брать данные из этих массивов.

Встаёт вопрос, насколько большие массивы получим? Стоит ли овчинка выделки?

В плане скорости будет быстрее, учитывая что мы можем пойти дальше и вычислить так же массивом g1 и g2 а может и дальнейший код.

-----------------------------------------------------------------
Я не знаю всего кода, но вполне возможно можно вынести весь вот этот кусок кода:
ArtProg
> v1 :=((scl_mul_x*(nt_pix_intr_sht_arr_ptr^+bmp_ftimg_left)+d1_)>>16);
> v2 :=((scl_mul_y*(nt_pix_arr_row_mrg_top+y+bmp_ftimg_top )+d2_)>>16);
> g1 := scl_mul.x*(nt_pix_intr_sht_arr_ptr^+bmp_ftimg_left)+d1;
> g2 := scl_mul.y*(nt_pix_arr_row_mrg_top+y+bmp_ftimg_top )+d2;
> px :=(Min(v1+1,g1+scl_mul.x)-Max(v1+0,g1));
> py :=(Min(v2+1,g2+scl_mul.y)-Max(v2+0,g2));
> bmp_bkgnd_ptr2 :=bmp_bkgnd_ptr+v1+v2*bmp_bkgnd_width;
и оставить вот только bmp_bkgnd_ptr2 как статический массив и брать из этого массива данные в данных циклах.

Другое не разбирал.

#14
(Правка: 1:56) 1:38, 25 сен 2022

Mirrel
  >выносим в самое начало:

yend := bmp_ftimg_height - nt_pix_arr_row_mrg_top - nt_pix_arr_row_mrg_btm - 1;
визуально лучше выглядит (о более понятно):


  Вот ведь эстеты). Я ж говорю, что красота меня пока что не интересует. И нужна ли она, если кодом все равно пользуюсь только я).
  О, насчет вспомогательного двухмерного массива(lookup table) кстати неплохая идея. Надо бы как-то проверить.
  Еще вопрос к последнему замечанию. Там же вроде как этот блок с каждым пикселем работает, ну то есть вынести за внутренний цикл? Очевидно, что работать не будет.

UPD. А хотя минуту, мой пробел, извиняюсь. Вынес v2 и g2 во внешний цикл. Стало получше. Глаз уже замылился однако).

Страницы: 1 2 315 16 Следующая »
ПрограммированиеФорумГрафика