Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.08.19;
Скачать: CL | DM;

Вниз

Обработка Bitmap двумя Thread   Найти похожие ветки 

 
Igor_K_A   (2007-06-07 05:21) [0]

Помогите решить проблему: есть Bitmap определенный в главном потоке программы и два дополнительных потока TThread, которые должны обрабатывать битмап парраллельно. Оброботка заключается в простом уменьшении разрешения - картинка бьется на ячейки, в каждой определяется доминирующий цвет и на сжатой картинке исходная картинка представляется уже одним пикселом. Замечен следующий баг: иногда выходная картинка закрашивается черным цветом на произвольную величину..а после этого выпадает "out of system resources". если использовать  
MyThread1.Resume;
MyThread1.WaitFor;  
MyThread2.Resume;
MyThread2.WaitFor;
вид запуска то все работает без ошибок и глюков, но теряется параллелизм :(


 
ЮЮ ©   (2007-06-07 08:03) [1]

Чисто интереса ради, какого размера твой Bitmap, что для такого элементарного, по сути, преобразования потребовальсь доп.потоки, да ещё два?


 
oxffff ©   (2007-06-07 09:00) [2]


> ЮЮ ©   (07.06.07 08:03) [1]
> Чисто интереса ради, какого размера твой Bitmap, что для
> такого элементарного, по сути, преобразования потребовальсь
> доп.потоки, да ещё два?


Многоядерность?


 
homm ©   (2007-06-07 13:59) [3]

> Многоядерность?

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


 
oxffff ©   (2007-06-07 14:36) [4]


> homm ©   (07.06.07 13:59) [3]
> > Многоядерность?
>
> Шишь он получит увеличение производительности на опирации
> интенсивной работы с памятью. Только если у него кривой
> алгоритм, излишне нагружающий процессор. Но в этом случае
> действуют не распаралеливанием, а улучшением алгоритма.


Поясни свой ответ


 
homm ©   (2007-06-07 14:40) [5]

> Поясни свой ответ

Мда… :)

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


 
oxffff ©   (2007-06-07 15:02) [6]


> homm ©   (07.06.07 14:40) [5]
> > Поясни свой ответ
>
> Мда… :)
>
> Распаралеливать нужно только когда все остальные способы
> увеличения производительности испробованы. К чему разносить
> на другой проц код, который делает лишнюю работу?


>Шишь он получит увеличение производительности на опирации
>интенсивной работы с памятью.

Не соозволите ли доказать сие свое утверждение?


 
oxffff ©   (2007-06-07 15:12) [7]

Tо homm
1. Читай про тенденции процессоростроения к  многоядерность
2. Читать про кэш память
3. Думать перед ответом.
4. Не засорять форум. ;)


 
oxffff ©   (2007-06-07 15:13) [8]

Кэш-память
Кэш-память представляет собой быстродействующее ЗУ, размещенное на одном кристалле с ЦП или внешнее по отношению к ЦП. Кэш служит высокоскоростным буфером между ЦП и относительно медленной основной памятью. Идея кэш-памяти основана на прогнозировании наиболее вероятных обращений ЦП к оперативной памяти. В основу такого подхода положен принцип временной и пространственной локальности программы.

Если ЦП обратился к какому-либо объекту оперативной памяти, с высокой долей вероятности ЦП вскоре снова обратится к этому объекту. Примером этой ситуации может быть код или данные в циклах. Эта концепция описывается принципом временной локальности, в соответствии с которым часто используемые объекты оперативной памяти должны быть "ближе" к ЦП (в кэше).

Для согласования содержимого кэш-памяти и оперативной памяти используют три метода записи:

Сквозная запись (write through) - одновременно с кэш-памятью обновляется оперативная память.
Буферизованная сквозная запись (buffered write through) - информация задерживается в кэш-буфере перед записью в оперативную память и переписывается в оперативную память в те циклы, когда ЦП к ней не обращается.
Обратная запись (write back) - используется бит изменения в поле тега, и строка переписывается в оперативную память только в том случае, если бит изменения равен 1.
Как правило, все методы записи, кроме сквозной, позволяют для увеличения производительности откладывать и группировать операции записи в оперативную память.


 
oxffff ©   (2007-06-07 15:14) [9]

Далее читать про разделяемый кэш и когерентность кэшей.


 
homm ©   (2007-06-07 16:11) [10]

> 1. Читай про тенденции процессоростроения к  многоядерность

Давай я тебе так намекну, без тенденций? Есть догадка, что автор пытается распаралелить процесс потому что он у него жутко торозит. А тормозит потому что Get\SetPixel. Сколько ядер тебе понадобиться, чтобы такой алгоритм работал хотя-бы со скоростью грамотно написаного для одного ядра на ассемблере? 128? 1024? Вперед, за тенденцией, удачи.


 
oxffff ©   (2007-06-07 16:17) [11]

>Оброботка заключается в простом уменьшении разрешения - картинка >бьется на ячейки, в каждой определяется доминирующий цвет и на сжатой >картинке исходная картинка представляется уже одним пикселом

Внимательно читал?


 
oxffff ©   (2007-06-07 16:20) [12]

Это уже кандидат на многопоточный алгоритм.
А что там у автора не получается. Не известно.


 
homm ©   (2007-06-07 16:20) [13]

> Внимательно читал?

Вполне. «каждой определяется доминирующий цвет». Это что по твоему, как не чтение?


 
oxffff ©   (2007-06-07 16:22) [14]


> Это что по твоему, как не чтение?


картинка бьется на ячейки и они не связаны.


 
homm ©   (2007-06-07 16:30) [15]

> картинка бьется на ячейки и они не связаны.

Физически? Логически? Автор придет, тогда поспоришь, любитель пофлудить.


 
tesseract ©   (2007-06-07 16:34) [16]


> Физически? Логически?


Если два ядра, то они явно будут разбросаны по памяти процессов/ядер, т.е физически.


 
oxffff ©   (2007-06-07 16:36) [17]


> homm ©   (07.06.07 16:30) [15]
> > картинка бьется на ячейки и они не связаны.
>
> Физически? Логически? Автор придет, тогда поспоришь, любитель
> пофлудить.


И это все что можешь сказать?

тогда читай oxffff ©   (07.06.07 15:12) [7]


 
oxffff ©   (2007-06-07 16:38) [18]


> tesseract ©   (07.06.07 16:34) [16]
>
> > Физически? Логически?
>
>
> Если два ядра, то они явно будут разбросаны по памяти процессов/ядер,
>  т.е физически.


Это к чему?


 
Igor_K_A   (2007-06-07 16:58) [19]

Ядра действительно два. Картинка бьется пополам и каждая половинка обрабатывается независимо. т.е. нет информационных зависимостей. Картинка большая. Необходим именно параллелизм..т.к. это тема на диплом :)) "распараллеливание больших задач"


 
Сергей М. ©   (2007-06-07 17:03) [20]


> Картинка бьется пополам


Показывай как "бьешь пополам" ...


 
Igor_K_A   (2007-06-07 17:10) [21]

MyThread1 := TMyThread.Create(true);
 MyThread1.bp:=0; //начало интервала обработки
 MyThread1.ep:=((Bit.Width div st) div 2)*st; //конец интервала обработки, st  шаг сетки
 MyThread1.Resume;
 MyThread1.WaitFor;  //////////

 MyThread2 := TMyThread.Create(true);
 MyThread2.bp:=((Bit.Width div st) div 2)*st+1;
 MyThread2.ep:=Bit.Width;
 MyThread2.Resume;
 MyThread2.WaitFor;  //////////
В таком виде работает все ок, но последовательно... если закоментировать строки помеченные ////////// тогда и начинаются все проблемы....причем даже если порождать один процесс то те же глюки


 
MBo ©   (2007-06-07 18:14) [22]

ты до сих пор не сказал, как к битмапу обращаешься


 
homm ©   (2007-06-07 18:24) [23]

Разбивай по ширине, а не по высоте на 2 части. В том коде, который ты привел вообще не понятно на что ты разбиваешь.


 
homm ©   (2007-06-07 18:25) [24]

> Разбивай по ширине, а не по высоте на 2 части.

Наоборот :)


 
Igor_K_A   (2007-06-07 18:27) [25]

procedure TMyThread.Execute;
begin
........
       BitOut.Canvas.Pixels[i div st,j div st]:=GetColorSubMap(i,j,st);// BitOut Bitmap для хранения сжатой картинки, тоже определен в главном потоке программы
........
function TMyThread.GetColorSubMap(x,y,step: integer):TColor;
var
 i,j,k: integer;
 max: integer;
begin
  dec(step);
  max:=0;
   for i:=x to x+step do
     for j:=y to y+step do
       begin
           if not(VL.FindRow(ColorToString(Bit.Canvas.Pixels[i,j]),k))  then
             VL.InsertRow(ColorToString(Bit.Canvas.Pixels[i,j]),"1",true)
           else
             VL.Cells[1,k]:=IntToStr(StrToInt(VL.Cells[1,k])+1);
       end;
   k:=0;
   for i:=1 to VL.RowCount-1 do
   begin
    if StrToInt(VL.Cells[1,i])>max then begin max:=StrToInt(VL.Cells[1,i]); k:=i; end;
   end;
     Result:=StringToColor(VL.Cells[0,k]);
     VL.Strings.Clear;
end;

end;


 
homm ©   (2007-06-07 18:35) [26]

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

2 oxffff
Что я говорил? Как тебе код? Считаешь, все еше считаешь что то что здесь нужно — распаралелить на 2 ядра?


 
MBo ©   (2007-06-07 18:41) [27]

крайне неразумно озадачиваться каким-то распараллеливанием, пока столько исключительно медленных операций даже в одной строке:
VL.FindRow(ColorToString(Bit.Canvas.Pixels[i,j]),k))  

тем не менее: обращение к Canvas.Pixels не может производиться одновременно из нескольких потоков, нужна синхронизация.


 
Anatoly Podgoretsky ©   (2007-06-07 19:42) [28]

Что и следовало ожидать, тут не распаралеливать нужно, а веники вязать.


 
oxffff ©   (2007-06-07 20:24) [29]


> homm ©   (07.06.07 18:35) [26]
> Мама дорогая. А потом этот «дипломник» будет разрабатывать
> программы для видеонаблюдения в аэропортах, от которых в
> какой-то степени будет зависеть моя жизнь. Помоему справедливо
> бкдет помочь только в том случае, если он пообкщает пойти
> торговать сотовыми телефонами, и больше не прикасатся к
> компилятору.
>
> 2 oxffff
> Что я говорил? Как тебе код? Считаешь, все еше считаешь
> что то что здесь нужно — распаралелить на 2 ядра?


Я останусь при своем мнении, так же как и ты.
Думаю ты не можешь со мной не согласиться.
И это не потому что не я такой, а это инициатива Intel, Amd, NVidia.
Многоядерность и все.
Поэтому уже сейчас он нас требуют "решать шире вопросы", чтобы производительность хорошо масштабировалась с добавлением "вычислительных ядер", естественно не GUI приложения.
А для задач подобной этой.
Stream processing и все

Другой вопрос это конкретный вопрос автора темы.
Что он хочет неизвестно.


> MBo ©   (07.06.07 18:41) [27]
> крайне неразумно озадачиваться каким-то распараллеливанием,
>  пока столько исключительно медленных операций даже в одной
> строке:
> VL.FindRow(ColorToString(Bit.Canvas.Pixels[i,j]),k))  
>
> тем не менее: обращение к Canvas.Pixels не может производиться
> одновременно из нескольких потоков, нужна синхронизация.
>

MBo ©   (07.06.07 18:41) [27]

Lock buffer eму в помощь


 
homm ©   (2007-06-07 20:27) [30]

> Я останусь при своем мнении, так же как и ты.
> Думаю ты не можешь со мной не согласиться.
> И это не потому что не я такой, а это инициатива Intel,
> Amd, NVidia.
> Многоядерность и все.

При чем тут многоядерность? Код стмотрел? Ему что, второе ядро поможет? Забудь про коня в вакууме.


 
oxffff ©   (2007-06-07 20:39) [31]


> homm ©   (07.06.07 20:27) [30]
> > Я останусь при своем мнении, так же как и ты.
> > Думаю ты не можешь со мной не согласиться.
> > И это не потому что не я такой, а это инициатива Intel,
>  
> > Amd, NVidia.
> > Многоядерность и все.
>
> При чем тут многоядерность? Код стмотрел? Ему что, второе
> ядро поможет? Забудь про коня в вакууме.


Ему пока нет. Но думаю до сдачи сделает. Во всяком случае надеюсь.


 
homm ©   (2007-06-07 20:47) [32]

> Ему пока нет.

А говорил что при своем мнении останешься :)


 
oxffff ©   (2007-06-07 20:50) [33]


> homm ©   (07.06.07 20:47) [32]
> > Ему пока нет.
>
> А говорил что при своем мнении останешься :)


Как тебе будет угодно. Но замечу мое мнение относилось к задаче, а не варианту решения этой задачи конкретным человеком.


 
Eraser ©   (2007-06-07 21:07) [34]

> [0] Igor_K_A   (07.06.07 05:21)

в многопоточном приложений при обращении к битмапу обязательно нужно использовать bmp.Canvas.Lock/Unlock иначе ошибки и глюки неминуемы.


 
Igor_K_A   (2007-06-07 21:32) [35]

Eraser, вы гуру! Мой вам респект! Коротко и ясно! Всем остальным тоже спасибо... алгоритм обязательно оптимизирую и убиру медленные куски


 
DVM ©   (2007-06-07 21:53) [36]


> Eraser, вы гуру! Мой вам респект! Коротко и ясно!

Только вот толку от многопоточности не будет никакой ибо пока один поток залочил битмап, другой будет ждать.


 
homm ©   (2007-06-07 22:01) [37]

> алгоритм обязательно оптимизирую и убиру медленные куски

Тебе не медленные куски убирать надо, а книжки читать и усиленно думать. Возьми для начала библиотеку какую, FastDib или какие еше там бывают. Это ДЛЯ НАЧАЛА. Был бы я на месте преподов, вообще бы оценку не ставил пока на ассемблере с использованием mmx бы не реализовал. Просто интересно, это все задание на диплом? Потому как это даже на 10-ю часть не тянет.


 
DVM ©   (2007-06-07 22:06) [38]


> Был бы я на месте преподов, вообще бы оценку не ставил пока
> на ассемблере с использованием mmx бы не реализовал

Как показывает практика можно и без асма сделать не хуже. А то и лучше. Ибо оптимизатор делфи генерит код очень хитро и лучше чем большинство программеров среднего уровня на асме.


> Igor_K_A   (07.06.07 18:27) [25]

Код хуже не бывает.

> Bit.Canvas.Pixels[i,j]),

Это чудовищно медленно. Можно написать раз в 100 быстрее работающее.


 
oxffff ©   (2007-06-07 22:07) [39]


> Igor_K_A   (07.06.07 21:32) [35]
> Eraser, вы гуру! Мой вам респект! Коротко и ясно! Всем остальным
> тоже спасибо... алгоритм обязательно оптимизирую и убиру
> медленные куски


Читать про GetDIBits


 
homm ©   (2007-06-07 22:23) [40]

> Как показывает практика можно и без асма сделать не хуже.
> А то и лучше. Ибо оптимизатор делфи генерит код очень хитро
> и лучше чем большинство программеров среднего уровня на
> асме.

Приятно знать, что я не «программер среднего уровня» в этом вопросе. Хотя, признать, без использования MMX как-то увеличить скорость грамотного(!) кода достаточно трудно.


 
Eraser ©   (2007-06-07 22:26) [41]

> [36] DVM ©   (07.06.07 21:53)


> Только вот толку от многопоточности не будет никакой ибо
> пока один поток залочил битмап, другой будет ждать.

а по-другому никак, GDI функции не потокобезопасны.

а толк будет, при условии, что один поток постоянно работает с битмапом, а другой, к примеру, только время от времени занимается прорисовкой этого битмапа на форме.


 
homm ©   (2007-06-07 22:30) [42]

> а толк будет, при условии, что один поток постоянно работает
> с битмапом, а другой, к примеру, только время от времени
> занимается прорисовкой этого битмапа на форме.

Можно не использовать GDI функции для обработки. См. [39]


 
oxffff ©   (2007-06-07 22:31) [43]


> а по-другому никак, GDI функции не потокобезопасны.


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


 
oxffff ©   (2007-06-07 22:33) [44]


> Поскольку этот буфер статичен (только чтение, используется
> как источник), то обращение к нему НЕ влечет за собой нагрузки
> на когерентность кэша при многоядерности и многосокетности
.
>


 
Eraser ©   (2007-06-07 23:05) [45]

> [43] oxffff ©   (07.06.07 22:31)

судя по задаче, автору проще создать 2 отдельных битмапа, а после обработки в отдельных потоках просто склеить их..


 
homm ©   (2007-06-07 23:14) [46]

> [45] Eraser

процедуру склейки не распаралелишь, к тому-же не понятно, чем «проще».


 
oxffff ©   (2007-06-07 23:16) [47]

Купить?


 
oxffff ©   (2007-06-07 23:17) [48]

Книгу естественно.


 
oxffff ©   (2007-06-07 23:27) [49]

to Igor_K_A
Вы нас всех хоть в соавторах диплома упомините.
Хотя больше на практическое задание смахивает.


 
Eraser ©   (2007-06-08 00:03) [50]

> чем «проще».

чем на свой страх и риск блокировать участки памяти.


 
homm ©   (2007-06-08 00:18) [51]

> чем на свой страх и риск блокировать участки памяти.

Зачем? Все проще. Делим попалам, один поток — один половину, другой — другую.


 
Pavia ©   (2007-06-10 02:53) [52]

На самом деле надо понять как работают паролельные процессы. Тогда все станет ясно. При работе с паролельными процессами важна синхронизация. Но так как в данном контексте процессы работуют каждый со своими данными, то все должно работать и без нее. Остается только правельно синхронизовать момент старта и остановки процессов.

Как программист со средним знанием асм скажу следующее. Дельфи генерирует безобразный код. Так, что если я перепишу на асм то программа будет работать быстрее в большинстве случиев. А если уж и использовать mmx, то точно прирост будет значительный.


 
Германн ©   (2007-06-10 03:01) [53]

а
> Pavia ©   (10.06.07 02:53) [52]

Вань. Лучше не позорься! Такое количество грамматических ошибок - явный перебор!


 
Strate ©   (2007-06-10 21:55) [54]

А можно разбить битмап на 2 битмапа, на каждый зафигачить поток который уменьшит его и потом соединить :)

Но наврено это глупо, т.к. разбивка и склеивание долго буту работать


 
Vovan Real   (2007-06-10 23:57) [55]

Удалено модератором
Примечание: в зеркало посмотри


 
homm ©   (2007-06-11 00:07) [56]

> [55] Vovan Real

Рад тебя снова видеть.


 
DVM ©   (2007-06-11 00:10) [57]


> Pavia ©   (10.06.07 02:53) [52]


> Дельфи генерирует безобразный код


> Так, что если я перепишу на асм то программа будет работать
> быстрее в большинстве случиев

А если я твой пост перепишу на нормальном русском языке и без ошибок, то прочтя его, ты сам, может быть, поймешь, что ты не совсем прав насчет безобразного кода, который генерит Делфи.



Страницы: 1 2 вся ветка

Текущий архив: 2007.08.19;
Скачать: CL | DM;

Наверх




Память: 0.63 MB
Время: 0.035 c
15-1185082566
dava
2007-07-22 09:36
2007.08.19
Редоктирование реестра запрешено администратором системы.


4-1171957830
Sunflower
2007-02-20 10:50
2007.08.19
Как удаленно установить клиентскую часть программы?


11-1168179075
Trible
2007-01-07 17:11
2007.08.19
поменять caption ы всех пунктов Меню


2-1185443040
ММК
2007-07-26 13:44
2007.08.19
Поворот TImage


1-1181650466
Max_
2007-06-12 16:14
2007.08.19
Шлейф, как с ним бороться ?