kaktus
-
Постов
8 -
Зарегистрирован
-
Посещение
Тип контента
Профили
Форумы
Загрузки
Блоги
Сообщения, опубликованные kaktus
-
-
Ура - 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
-
Хм... Всё страньше и страньше ...
Напоминаю - программа заполняет две области 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: Если я пишу где-то глупость, то не стесняйтесь поправляйте меня. Я полез
Куда Макар телят не гонялв несвойственные мне дебри и естественно буду косячить, -
Цитата
... SetPixel это вообще супер медленный метод! ...
Да это вобщем-то неважно, речь идёт о том что параллельная работа с GDI невозможна. Не нравится SetPixel - попробуй TextOut раз 500 на поток. Окажется что в однопотоке это всё выполняется быстрее чем в многопотоке. А если попытаться проследить выполнение кода - окажется, что потоки встают в очередь и выполняются последовательно.
Цитата... А несколько потоков простых, например созданных через CreateThread и работающих со своими bitmap вообще никак не могут друг друга заблокировать...
- Угу, я тоже так думал. Попробуй на C++ это сотворить - сильно удивишся.
Блокировка идёт не на уровне bitmap (я про тот который HBITMAP потому что tBimap считается потокобезопасным, а значит однозначно набит Locka-ами/UnLock-ами )
и блокировка идёт даже не на уровне bitmap а скорее либо на уровне драйвера видеокарты (и CompatibleDC тут не спасает) либо сама Windows не позволяет выполнять графические функции API в нескольких потоках.
Цитата...это всё язык на котором ты пишешь и его навороты...
Та там практически чистый API. Всякие удобные обёртки типа tThread к проблеме отношения не имеют. Посмотри код который я приложил - он хорошо документирован. Попробуй его выполнить на C++ тогда поймёшь масштаб беды
Я конечно могу на С++ пример приложить, но на это уйдёт крайне много времени т.к. мне придётся начинать с установки среды программирования. И программу на C++ мне придётся писать чуть ли не с букварём. Я надеюсь что на форуме есть люди которые умеют и C++ и ObjectPascal.
-
Про SendMessage в SetPixel я конечно погорячился но мне простительно, это я от отчаяния. (Что конечно не отрицает возможности наличия других типов блокировок в графических функциях GDI) Привожу максимально упрощённый код для тестирования многопоточной отрисовки. К качеству прошу не придираться - код для демонстрации.
https://fex.net/ru/s/lxdcmrp
не смог найти как прикрепить файл к форуму, через некоторое время ссылка протухнет и для потомков ничего не останется.ps: С++ я тоже понимаю со словарём Поэтому если кто-нибудь решится привести рабочий пример многопоточной отрисовки на C++ это тоже будет считаться благородным поступком и зачтётся плюсиком в карму.
-
Я так делал : Создавал несколько CompatibleDC/Compatible bitmap в основном потоке и отпускал DC. Затем запускал потоки и после
их завершения освобождал Compatible ресурсы. Увы - тоже не взлетело.
А как прикрепить файл - rar архив,? Я не нашёл.
ps: Мне почему то кажется, что сама операция SetPixel содержит код который включает механизм блокировки, (например SetPixel вызывает SendMessage) я в гугле нашёл множество аналогичных вопросов на эту проблему, но не нашёл ни одного решения - кроме отсылок к msdn и уверений, что это возможно "мамой клянусь". Я больше склоняюсь к мысли что это невозможно и придётся работать с массивами и низкоуровневыми алгоритмами отрисовки.
-
Я так и делал, вот код потока
Спойлер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 блокировало) - но нет, не помогло.
-
Thread(N).Bitmap.Canvas.Pixels[x,y] наверняка лочится, однако я отрабатывал множество разных вариантов, в том числе и вариант API SetPixel(DC,X,Y,Color) - увы он тоже лочит потоки.
-
Здравствуйте. Кто может подсказать по поводу многопоточной отрисовки графики посредством
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
Многопоточный GDI
in Высокоуровневое программирование
Опубликовано
Ты предложил - и я услышал. Тестирование DIB секций я начал с твоей подачи. Тебе большое человеческое спасибо.