Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - .NET

Страница: 1 | 2 | 3 |

 

  Вопрос: Параллельный ParallelBitmap Добавлено: 25.02.11 21:04  

Автор вопроса:  VβÐUηìt | Web-сайт: смекаешь.рф
Есть такое? Ну чтобы


using (var g = Graphics.FromImage(bitmap))
   Parallel.For(0, 10, i=>
      {
           g.DrawString(0, i * 10, "Жрать");
      });


в смысле если нет, то придется делать вручную его и все методы Graphics для параллельного режима, а это так скушно... Так что хотелось бы, чтобы кто-то уже раз столкнувшийся с этой проблемой запилил кошерный класс.

Суть такова: обычный Bitmap не позволяет работать с собой в многопоточном режиме. Нужен класс, который это делать позволяет, то есть битмап с многопоточным доступом. Если чувак делает какой-нибудь маразм, а-ля из 20 потоков рисует в одном и том же месте, то это его проблемы (на деле все сводится к изменению цветовых компонент, которое само по себе атомарно). То есть, скажем метод DrawString сначала рисует на своем буфере, а затем копирует в указанное место, даже если перехлествается с другим потоком.

Заранее благодарен.

Ответить

  Ответы Всего ответов: 38  

Номер ответа: 1
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #1 Добавлено: 25.02.11 23:30
попробуй сделать наследника от Bitmap и, повторяя все его члены, в необходимых местах пиши lock (_syncRoot) {} . возможно прокатит.

Ответить

Номер ответа: 2
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #2 Добавлено: 25.02.11 23:52
А давно это битмап наследоваться начал?

Ответить

Номер ответа: 3
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #3 Добавлено: 25.02.11 23:54
Parallel.For

предназначен для распреления задачи по ядрам процессора и к многопоточности отношения не имеет.. То? что тебе надо? делается 1 строкой из Invoke/BeginInvoke// можешь завернуть в свой метод

Ответить

Номер ответа: 4
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #4
Добавлено: 26.02.11 00:30
Мне не нужно, чтобы он делал Lock. Мне нужно, чтобы несколько отдельных потоков/ядер/срать могли в разных местах одновременно на нем рисовать. Производительность. Если я буду делать Lock, то прироста никакого это не даст. Ибо из WPF нормально копировать отрендеренный видеокартой красивый результат копировать научился только лютым хаком. Вот. Поэтому приходится процессором. А раз процессором, то почему за перерисовку может отвечать максимум 1 ядро? Тогда уж все. Распиливать битмап пополам для двух ядер и рисовать отдельно не предлагать - рисоваться может запросто что-то, что находится в обоих частях. Например текст.

Ответить

Номер ответа: 5
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #5 Добавлено: 26.02.11 01:54
почему за перерисовку может отвечать максимум 1 ядро?

Ну наверное потому,что GDI разрабатывался стопиццот лет назад,когда про многоядерные процессоры еще и не мечтали. Имхо,нифига у тебя не выйдет.. Graphics не допустит одновременного доступа из разных потоков и без lock тебе по любому не обойтись.. И это ограничение не НЕТ а именно GDI

Ответить

Номер ответа: 6
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #6
Добавлено: 26.02.11 05:58
  1.  
  2. public struct Color { public int r,g,b; }
  3.  
  4. public unsafe class ParallelBitmap
  5. Color[] Pixel;
  6. void ParallelBitmap(int width, int height)
  7. {
  8.        Pixel = new Color[width,height];
  9. }



Далее создаю копии всех функций Graphics. Каждая функция рисует ботву на собственном битмапе в отдельном потоке, а затем копированием декималом по 96 бит сливает в массив. В массив сливать можно параллельно, так что пофиг. Если при этом еще продумать, чтобы для каждой операции не выделялся каждый раз новый битмап, то все вообще было круто. Сделать это можно так: создаем массив из стольких битмапов, сколько есть на компе. Все размером с сам ParallelBitmap. Каждая операция берет свободный битмап и рисует на нем, копиурет результат в основной, затем ложит битмап обратно. Если в данный момент свободных битмапов нет, ждет, пока они появятся. Бо?

Ответить

Номер ответа: 7
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #7
Добавлено: 26.02.11 05:59
EROS пишет:
Сделать это можно так: создаем массив из стольких битмапов, сколько есть на компе.

*сколько есть на компе ядер))

Ответить

Номер ответа: 8
Автор ответа:
 AWP



ICQ: 345685652 

Вопросов: 96
Ответов: 1212
 Web-сайт: xawp.narod.ru
 Профиль | | #8
Добавлено: 26.02.11 08:58
Ну с массивом из разных потоков я работал, вроде не вылетало.
Потом можно
SetDIBitsToDevice
или
SetDIBits

Но я так понимаю, что тебе видеокартой нужно?

Ответить

Номер ответа: 9
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #9
Добавлено: 26.02.11 13:23
Раньше нужно было. Но там другая история - тупо рисуем все в WPF видеокартой, а потом забирать от туда. RenderTargetBitmap рисует все процессором, и производительность ужасна. Поэтому решил вернуться к GDI, который тоже медленный :) Но его можно распараллелить, то есть использовать для прорисовки все ядра процессора, а не одно. Тогда получается более-менее нормально.
Я хочу запилить примерно это:
  1.  
  2. using (var bmp = ParallelBitmap.FromImage("background.png"))
  3.   Parallel.For(0, 10, i=>
  4.    Parallel.Invoke(
  5.       ()=>bmp.DrawCircle(50,i, 300),
  6.       ()=>bmp.DrawString(50, i, i.ToString()),
  7.       ()=>bmp.DrawImage(bmpIllustration, i, i)
  8.       ));


То есть спокойно параллельно рисуем все прямо на битмапе разными ядрами. Или потоками - не суть. И никаких "другой поток использует Bitmap". В данном примере это особой роли в производительности не даст, но там, где это поланируется использовать, прирост должен быть существенным.

Функции ParallelBitmap, которые используют Windows API, рисуют свое дело на отдельных битмапах в своем потоке, затем в нем же переносят в 2D-массив цветов.

Функции, которые не требуют WindowsAPI (например, DrawImage - можно спокойно самому написать побайтовое (или по 4 байта для 32x) копирование), рисуют все прямо сразу по массиву, не используя других битмапов и экономя ресурсы на копировании. Бо?

Ответить

Номер ответа: 10
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #10 Добавлено: 26.02.11 14:32
бо-то бо, а ты пробуй и делай бенчмарки

Ответить

Номер ответа: 11
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #11 Добавлено: 27.02.11 12:09
рисуют все прямо сразу по массиву

в таком случае Scan0 + unsafe тебе в помощь

Ответить

Номер ответа: 12
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #12
Добавлено: 27.02.11 13:21
Мне тут сказали, что оказывается можно создать несколько битмапов на одной и той же памяти. То есть битмапов какбэ, скажем, два, но память у них одна. Как это запилить?

Ответить

Номер ответа: 13
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #13 Добавлено: 27.02.11 18:19
CopyMemory как вариант?

Ответить

Номер ответа: 14
Автор ответа:
 VβÐUηìt



Вопросов: 246
Ответов: 3333
 Web-сайт: смекаешь.рф
 Профиль | | #14
Добавлено: 27.02.11 22:22
Нееет. Нужно чтобы было два класса Bitmap, которые ссылаются на один и тот же кусок памяти. Чтобы лохануть WinAPI. Народ говорил, что работает. То есть мы из двух потоков рисуем на разных битмапах, но на деле работаем с одним куском памяти. Без копирований.

Ответить

Номер ответа: 15
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #15 Добавлено: 28.02.11 02:07
можно создать несколько битмапов на одной и той же памяти.

Так спроси у того,кто такое сказал. Я даже не догоняю что имелось ввиду.. как у 2 разных объектов может быть одна память??? имхо, бред..

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам