Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Крайне медленное обращение к массиву

21K
26 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Приветствую всех. Сам я пока начинаю программировать в Visual C++ .NET, но имею значительный опыт программирования в Visual Basic 6.0. Так вот, сейчас занимаюсь графическими алгоритмами. Сначала сделал битмап, привязал к нему указатель и работал как с одномерным массивом типа char. Скорость была вполне приличная (по сравнению с VB). Потом я сделал одномерный массив типа int, чтобы создать HDR-картинку и потом переводить в LDR. И тут начались тормоза. Есть вот такой цикл.
 
Код:
for(a=0;a<IMAGESIZE;a++)
    { fore[a]=gamma[max(min(hdrb[a],4095),0)]; }

Без него прога работает вхолостую, выдавая где-то 320 кадров в секунду. С циклом на AthlonXP 2000+ выдает 90, хотя IMAGESIZE составляет всего-то 921600 (640*480*3), а действия в цикле - взятие числа, клиппинг и гамма-коррекция по байтовой таблице из 4096 значений. Есть еще один HDR-буфер для осуществления размытия картинки:
 
Код:
memcpy(hdrb2,hdrb,IMAGESIZE*4);

И даже функция memcpy, копируя каждый кадр чуть больше 3.5 мегов, сбрасывает fps до 40 с небольшим.
И есть алгоритм размытия. Я переписал его с VBшной проги на C++. Вариант, который копирует данные из hdrb2 в hdrb, размывая по пяти соседним пикселам, выдает около 17 кадров в секунду, а вариант без двойного буфера (и без memcpy) - 22, в то время как тот же алгоритм, написанный на VB, работает, выдавая 38 кадров, то есть, почти вдвое быстрее. Даже если учесть, что алгоритм не совсем оптимизирован, это довольно странно. Да и оптимизации в свойствах проекта включены. Из-за чего такое может происходить? Почему обращение к памяти даже при прямом построчном считывании занимает десятки каменных тактов, как будто у процессора нет кэш-памяти? Я уж думал, что в Си таких проблем не возникнет...
7.6K
26 ноября 2006 года
Darien
125 / / 15.01.2006
Ты работает с видеопамятью или с физической ?
21K
26 ноября 2006 года
CraigFatman
10 / / 26.11.2006
С физической RAM, которая на мамке... на видео пока лазить не собираюсь.
5.4K
26 ноября 2006 года
Svyatozar
221 / / 11.09.2006
Цитата: CraigFatman
С физической RAM, которая на мамке... на видео пока лазить не собираюсь.


и напрасно.

21K
26 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Цитата:
и напрасно.


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

5.4K
27 ноября 2006 года
Svyatozar
221 / / 11.09.2006
Цитата: CraigFatman
В смысле, если я буду выводить битмап не в окно, а напрямую в память видеоадаптера, у меня все полетит? Это, конечно сократило бы издержки при выводе окончательного изображения, но я ведь не про это спрашивал...

Да мало ли в чем причина может быть. Код использует MMX?

21K
27 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Цитата:
Код использует MMX?


По идее не использует, хотя фиг знает, что генерит компилятор. Может, у меня настройки компиляции какие-то левые?

5.4K
28 ноября 2006 года
Svyatozar
221 / / 11.09.2006
Может ты используешь отладочные библиотеки рунтайма?

В дебаггере нельзя зайти внутрь функции memcpy()?

Вообще трудно так дистанционно гадать по-экстрасенсовски что там у тебя по ходу откомпилировалось...
21K
28 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Цитата:
В дебаггере нельзя зайти внутрь функции memcpy()?


В режиме компиляции Debug заходит внутрь, в режиме Release - нет.

Цитата:
трудно так дистанционно гадать по-экстрасенсовски


Может выложить сюда исходник? Глянь, может разберешься, в чем тут дело... он для нетовской версии...
[ATTACH]1271[/ATTACH]

21K
29 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Вот, нарыл-таки функцию дисассембляции. Этот цикл просто заливает картинку одним цветом:

Код:
for(a=0;a<IMAGESIZE;a++) {
00403895  mov         ecx,dword ptr [IMAGESIZE (41AD6Ch)]
0040389B  xor         eax,eax
0040389D  test        ecx,ecx
0040389F  mov         dword ptr [esp+24h],0
004038A7  jle         drawframe+7Bh (4038DBh)
}
004038A9  lea         esp,[esp]
        *(fore+a)=192; a++;
004038B0  mov         ecx,dword ptr [fore (4136E8h)]
004038B6  mov         byte ptr [ecx+eax],0C0h
    *(fore+a)=192; a++;
004038BA  mov         edx,dword ptr [fore (4136E8h)]
004038C0  inc         eax  
004038C1  mov         byte ptr [edx+eax],0C0h
    *(fore+a)=192;
004038C5  mov         ecx,dword ptr [fore (4136E8h)]
004038CB  inc         eax  
004038CC  mov         byte ptr [ecx+eax],0C0h
004038D0  mov         ecx,dword ptr [IMAGESIZE (41AD6Ch)]
004038D6  inc         eax  
004038D7  cmp         eax,ecx
004038D9  jl          drawframe+50h (4038B0h)
    }

Сам цикл - это 12 последних инструкций. Только вот больно тяжело эти инструкции даются машине. Пробовал с циклом и без него - 180 и 320 кадров в секунду соответственно, хотя повторяется цикл всего-то 307200 раз. Что самое интересное, цикл, выполняющий билинейную интерполяцию трех компонент цвета (каждый угол экрана имеет свой цвет) выполняется практически с той же скоростью, что и простое заполнение! Походу, оно так сильно тормозит, что затмевает собой все вычисления...
21K
30 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Хех... сейчас запихал этот луп в виде асмовой вставки и немного поизвращался над ним. Тут повторяются восемь инструкций, которые (по идее) должны спариваться и выполняться за четыре такта. На моем проце 307200 повторов - это менее тысячной доли секунды. Но скорость увеличилась совсем чуть-чуть. Что-то я не догоняю...
Код:
__asm
{
  //  for(a=0;a<IMAGESIZE;a++) {
  mov         ecx,dword ptr [IMAGESIZE]
  xor         eax,eax
  test        ecx,ecx
  mov         dword ptr [esp+24h],0
  jle         l2
  lea         esp,[esp]
  mov         edx,dword ptr [IMAGESIZE]
  mov         ecx,dword ptr [fore]
  add         eax,ecx
  add         edx,ecx
  //        *(fore+a)=192; a++;
l1:
  mov         byte ptr [eax],0E0h
  //    *(fore+a)=192; a++;
  inc         eax  
  mov         byte ptr [eax],0D0h
  //    *(fore+a)=192;
  inc         eax  
  mov         byte ptr [eax],0C0h
  inc         eax
  cmp         eax,edx
  js          l1
l2:
}
5.4K
30 ноября 2006 года
Svyatozar
221 / / 11.09.2006
"307200 повторов - это менее тысячной доли секунды" ??? :eek: А ты посчитал сколько в каждом повторе обращений к памяти?
252
30 ноября 2006 года
koderAlex
1.4K / / 07.09.2005
оффтоп:вот читаю и удивляюсь . излишний расход оперативы (и тактов)устроили только .
21K
30 ноября 2006 года
CraigFatman
10 / / 26.11.2006
Цитата:
А ты посчитал сколько в каждом повторе обращений к памяти?


По три обращения на каждый пиксел. Но запись будет (должна) производиться в L1 cache, а в оперативку скидываться только когда запишется полная кэш-линия. И никаких задержек быть не должно.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог