Перейти к содержанию

kaktus

Стажёры
  • Постов

    8
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные kaktus

  1. В 20.08.2020 в 21:41, Xipho сказал:

    Проверь, если не поможет, попробуй переключиться на DIB секции. У меня в уроке по созданию трейнера на плюсах есть работа с диб секциями

     

    Ты предложил - и я услышал. Тестирование DIB секций я начал с твоей подачи. Тебе большое человеческое спасибо. :)

  2. Ура - DIB работает !!! И все странности со временем выполнения пропали. Скорость отрисовки тоже повысилась. 1 столбец - 10мсек. 2 столбца 14 мсек. Я так-же очень доволен тем фактом что нужные мне графические функции API типа TextOut поддерживают полноценную работу с DIB. Так-же

    приятный бонус, что теперь можно писать напрямую в массив памяти и несомненно это будет быстрее чем SetPixel 

    (.... не выдержал, проверил - 2 мсек. Более чем 10и кратное ускорение, если учитывать накладные расходы на обслуживание потоков..)

     

    Предварительные выводы -

    1.CreateCompatibleBitmap создаёт BITMAP привязанный к дайверу видеокарты (возможно к памяти видеокарты)

    2. Параллелить вывод (если позволяет логика приложения) можно используя DIB секции. А судя по странностям с задержками вывода на основной DC так вообще предпочтительнее выводить сначала в DIB а потом BitBlt в основной DC. Всё равно народ в основном через двойной буфер выводит, так и пусть этот буфер будет DIB типа.

    3. DIB секции поддерживают графические операции API и прямой доступ к плоскости изображения и скорее всего поддерживают все графические функции API (например кривые Безье)

    4. Я маньяк (волосы торчат, глаза красные - пора спать)

     

    Если какие вопросы будут - пишите в ветку, спрашивайте. Я ещё какое-то время сюда буду заходить на всякий случай.

    • Плюс 1
  3. Хм... Всё страньше и страньше ...

    Напоминаю - программа заполняет две области 400x100 случайными пикселями.

    Мучая несчастный GDI заметил такую странность. (Я сейчас исключительно про однопоточный режим. Вся работа происходит в основном потоке программы). Время работы программы меняется непредсказуемым образом, но принимает всего три значения - 32 мсек. 86мсек и 130мсек. ну плюс/минус конечно.

    Измеритель у меня точный - QueryPerfomanceCounter, не какой-нибудь там GetTickCount :). Комп не занят, 4ре ядра... Ещё страньше то, что API SetPixel выполняется дольше чем Canvas.SetPixels[x,y] Хотя  Canvas.SetPixels обёртка вокруг API SetPixel. Чудеса вобщем. Ну да ладно - это чисто теоретический интерес, пока отложим.

    Приятная новость заключается в том, что под Win7 время заполнения на нескольких потоках по крайней мере не больше чем на одном потоке. Уже радует. Ложка дёгтя тут заключается в том, что есть некая технологическая программа, которая работает исключительно на winXP (HASP, там ... все дела). И на таких компах ускорения отрисовки не получится. Хотя возможно и Windows7 не взлетит, проверю - напишу результат.

    Далее по плану помучать DIBsection. Есть подозрение что CompatibleDC это всё таки про видеокарту и соответственно не shared ресурс, а DIB это про ОЗУ и возможно windows не будет разделять доступ к таким ресурсам.

    ps: Если я пишу где-то глупость, то не стесняйтесь поправляйте меня. Я полез Куда Макар телят не гонял в несвойственные мне дебри и естественно буду косячить,

  4. Цитата

    ... SetPixel это вообще супер медленный метод! ...

    Да это вобщем-то неважно, речь идёт о том что параллельная работа с GDI невозможна. Не нравится SetPixel - попробуй TextOut раз 500 на поток. Окажется что в однопотоке это всё выполняется быстрее чем в многопотоке. А если попытаться проследить выполнение кода - окажется, что потоки встают в очередь и выполняются последовательно.

     

    Цитата

    ... А несколько потоков простых, например созданных через CreateThread и работающих со своими bitmap вообще никак не могут друг друга заблокировать...

    - Угу, я тоже так думал. Попробуй на C++ это сотворить - сильно удивишся.

    Блокировка идёт не на уровне bitmap (я про тот который HBITMAP потому что tBimap считается потокобезопасным, а значит однозначно набит Locka-ами/UnLock-ами )

    и блокировка идёт даже не на уровне bitmap а скорее либо на уровне драйвера видеокарты (и CompatibleDC тут не спасает) либо сама Windows не позволяет выполнять графические функции API в нескольких потоках.

     

    Цитата

    ...это всё язык на котором ты пишешь и его навороты...

    Та там практически чистый API. Всякие удобные обёртки типа tThread к проблеме отношения не имеют. Посмотри код который я приложил - он хорошо документирован. Попробуй его выполнить на C++ тогда поймёшь масштаб беды :)

     

    Я конечно могу на С++  пример приложить, но на это уйдёт крайне много времени т.к. мне придётся начинать с установки среды программирования. И программу на C++ мне придётся писать чуть ли не с букварём. Я надеюсь что на форуме есть люди которые умеют и C++ и ObjectPascal.

  5. Про SendMessage в SetPixel я конечно погорячился :) но мне простительно, это я от отчаяния. (Что конечно не отрицает возможности наличия других типов блокировок в графических функциях GDI) Привожу максимально упрощённый код для тестирования многопоточной отрисовки. К качеству прошу не придираться - код для демонстрации.

    https://fex.net/ru/s/lxdcmrp
    не смог найти как прикрепить файл к форуму, через некоторое время ссылка протухнет и для потомков ничего не останется.

    ps: С++ я тоже понимаю со словарём :) Поэтому если кто-нибудь решится привести рабочий пример многопоточной отрисовки на C++ это тоже будет считаться благородным поступком и зачтётся плюсиком в карму.

     

  6. Я так делал : Создавал несколько CompatibleDC/Compatible bitmap в основном потоке и отпускал DC. Затем запускал потоки и после

    их завершения освобождал Compatible ресурсы. Увы - тоже не взлетело.

    А как прикрепить файл - rar архив,? Я не нашёл.

    ps: Мне почему то кажется, что сама операция SetPixel содержит код который включает механизм блокировки, (например SetPixel вызывает SendMessage) я в гугле нашёл множество аналогичных вопросов на эту проблему, но не нашёл ни одного решения - кроме отсылок к msdn и уверений, что это возможно "мамой клянусь". Я больше склоняюсь к мысли что это невозможно и придётся работать с массивами и низкоуровневыми алгоритмами отрисовки.

  7. Я так и делал, вот код потока 

    Спойлер
    
      mainDC := GetDC(vHndl);
    
      Try
    
       fDC     := CreateCompatibleDC (mainDC);
       fBitmap := CreateCompatibleBitmap (mainDC,400,100);
    
       oldBitmap := SelectObject (fDC,fBitmap);
    
       For iy := 0 To 100 - 1 Do
        For ix := 0 To 200 - 1 Do
         SetPixel(fDC,ix,iy,RGB (random(255),random(255),random(255)));
         
      SelectObject (fDC,oldBitmap);
      DeleteObject(fBitmap);
      DeleteDC(fDC);
    
      ReleaseDC(vHndl,mainDC);
    
      Finally
       InterlockedDecrement(DV^);
      End;

     

    Это было для проверки времени выполнения и до вывода результата даже не дошло. Если закомментить  SetPixel - то блокировок не возникает на любом количестве потоков. Однако любая графическая операция тут же начинает блокировать поток. Потоки начинают выполнятся последовательно. Я даже делал так - создавал и удалял CompatibleDC в основном потоке (использовал массив) а потокам раздавал уже готовый bitmap ( думал что может GetDC блокировало) - но нет, не помогло.


  8. Здравствуйте. Кто может подсказать по поводу многопоточной отрисовки графики посредством
    GDI ?
    Суть в следующем - экран разбит на 5 столбцов шириной примерно 200 пикселей. В каждый столбец
    рисую несколько графиков используя Canvas.Pixels либо Canvas.MoveTo,LineTo. С целью ускорения вывода
    сделал отрисовку каждого столбца в своём потоке, а после отрисовки всех столбцов многопоточно,далее 
    в основном потоке делаю вывод на экран посредством Canvas.Draw. Для каждого столбца создаётся 
    своя bitmap на собственном CompatibleDC.Однако скорость не увеличивается, а наоборот уменьшается и 
    довольно сильно. Путём отладки выяснил, что в момент выполнения Canvas.Pixels поток лочится и другие 
    потоки не работают.

    Ещё раз повторю для каждого потока создаётся собственная bitmap привязанная к совственному CompatibleDC.
    т.е. при выполнении Thread(N).Bitmap.Canvas.Pixels[x,y] := RandomColor все остальные Thread лочатся
    до завершения операции в Thread(N). И не просто до завершения, а лок висит ещё довольно долго, что
    приводит к увеличению времени отрисовки по срвнению с однопоточным режимом. Реальные цифры таковы

    в однопоточном режиме заполнение одного столбца 400X100 случайными пикселями происходит примерно 
    за 16 мсек. Двух столбцов 32 мсек.

    В многопоточном режиме - один столбец,один поток (блокировок потоков не возникает) 16мсек.
    два столбца, два потока 210 мсек. (чем больше столбцов тем дольше рисует по сравнению с однопотоком)

    выход пока видится только в создании массивов плоскостей пикселей не привязанных ни к какому DC
    и отрисовка на этих плоскостях графических примитивой с помощью например алгоритмов Брезенхема.
    Но хотелось бы DrawText со всем шрифтовым богатством Windows.

    Вопрос в следующем - рисовал ли кто в многопотоке функциями GDI и каким образм ?
    ps: WinXp / Delphi7

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.