0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
||||||
1 | ||||||
Параллельное программирование08.10.2016, 01:26. Показов 4764. Ответов 23
Метки нет (Все метки)
Решил накидать простенькую задачу: выполнить какие-нибудь операции над большим блоком данных. И это все распараллелить. Это можно сделать 2мя способами:
1. Параллелить вызов коротеньких процедур. Но тогда будет очень много времени тратиться на то, чтобы передать управление другому ядру. Ведь так? ну нет смысла параллелить операцию 2+2. 2. Параллелить обработку блоков данных. Логично предположить. что когда параллельно запускаться будут тяжелые процедуруы, эффект от параллельности будет гораздо выше. Однако оказались весьма странные результаты. Почему-то первоначальный эффект от параллельности отрицательный. Вот код простой программки, которая наглядно всё демонстрирует:
1 итерация: 1 поток, время: 2,5947303 2 поток, время: 1,5046816 3 поток, время: 1,2435103 4 поток, время: 1,1743574 5 поток, время: 1,8177255 6 поток, время: 1,8564871 7 поток, время: 1,7038264 8 поток, время: 1,7404472 Блок итераций: 1 поток, время: 1,2824387 2 поток, время: 1,2592897 3 поток, время: 1,3303499 4 поток, время: 1,3710368 5 поток, время: 1,4195757 6 поток, время: 1,4460356 7 поток, время: 1,5213963 8 поток, время: 1,6072681 Как видно, во втором случае результат очень плохой. То есть распараллеливание медленно отрабатывает. Почему так? Ведь по логике второй способ распараллеливания должен быть лучше первого?
0
|
08.10.2016, 01:26 | |
Ответы с готовыми решениями:
23
Параллельное программирование Нужны задачи на параллельное программирование Служба Windows и параллельное программирование Параллельное программирование и библиотека TPL |
08.10.2016, 09:48 | 2 |
Dimarik__1, на RSDN была неплохая статья на эту тему (немного вольный перевод глав из книги Албахари), но сейчас ее уже нет, как видно удалили. У меня есть копия в pdf, вот прикрепляю, почитайте. Довольно интересный материал.
3
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
|||||||||||
09.10.2016, 22:44 [ТС] | 3 | ||||||||||
Спасибо. Прочитал. Ну получается, для данного примера следует использовать либо Parallel.For либо PINQ. Однако Parallel.Fro более оптимизирован. Написано что лучше не использовать внутреннее распараллеливание так как оно медленнее отрабатывает чем внешнее. Я так и сделал. Тем не менее странные результаты, которые не объясняются никак. А моя задача максимально эффективно распараллелить.
Добавлено через 22 часа 54 минуты Вы можете подсказать, как можно написанный мной код переписать с использованием PLINQ? Добавлено через 7 часов 10 минут Я нашел вот такое в Интернете.
Спасибо Добавлено через 1 час 45 минут Можете пояснить, почему цикл for выполняется быстрее чем parallel.For?
Time with parallel = 56,7273746
0
|
1150 / 742 / 483
Регистрация: 21.01.2014
Сообщений: 1,903
|
|
09.10.2016, 23:33 | 4 |
0
|
Неадекват
1492 / 1230 / 246
Регистрация: 02.04.2010
Сообщений: 2,789
|
|
09.10.2016, 23:34 | 5 |
Потому что st1 замеряет параллельную версию, но в результатах пишется как последовательная...
1
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
|||||||||||
10.10.2016, 00:03 [ТС] | 6 | ||||||||||
да. Вы правы. Както проглядел. А по поводу основного сообщения темы, вы можете дать ответ? Спасибо.
Я эту проверку с циклом for делал чтобы получше понять Perallel.For. В основной программе у меня следующая проблема возникла. Вот участок кода
Вот эта функция
Добавлено через 6 минут как один из вариантов, из-за GC.Collect() Убрал я его. В результате время при числе потоков следующее 1: 4 сек 2: 11 сек 3: 22 сек 4: 44 сек
0
|
Неадекват
1492 / 1230 / 246
Регистрация: 02.04.2010
Сообщений: 2,789
|
|
10.10.2016, 00:29 | 7 |
Dimarik__1, не понятно, что вы хотите распараллелить. Опишите задачу.
0
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
||||||
10.10.2016, 09:54 [ТС] | 8 | |||||
У меня есть картинка, на которой на белом фоне сфотографированы яблоки. Мне нужно выделить каждое яблочко в отдельную картинку и сегментировать каждое яблочко.
Я делаю это следующим образом: 1. Получаю контуры каждого яблока. Вот здесь они хранятся 2.И затем создаю список объектов listObjectsWork[iCountInList].allObjects, в каждом из которых будет единичных объект яблоко, которое разбито на сегменты. У меня в конструкторе происходит выделение яблоко в отдельный объект из общего изображения. И затем сегментация. Может быть у меня тормоза идут из-за того что я к одному общему объекту постоянно обращаюсь? Вот код конструктора:
0
|
Неадекват
1492 / 1230 / 246
Регистрация: 02.04.2010
Сообщений: 2,789
|
|
10.10.2016, 11:34 | 9 |
Dimarik__1, боюсь, без OpenCV на такой задаче вменяемых скоростей вы не получите. Хоть с TPL, хоть без нее.
0
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
|
10.10.2016, 11:42 [ТС] | 10 |
Так у меня EMGUCV. EMGUCV это и есть OpenCV но под шарп.
И вопрос именно в распараллеливании. Почему при распараллеливании скорость падает
0
|
.NET senior
440 / 358 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
||||||
10.10.2016, 11:44 | 11 | |||||
Dimarik__1, попробуйте воспользоваться примером из code gallery с сайта emgu.cv:
Кликните здесь для просмотра всего текста
В тесте без всякой параллельности детектирование яблок прокручивается за ~1 секунду. Анализируемое и результирующее изображение - во вложениях.
0
|
.NET senior
440 / 358 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
|
10.10.2016, 11:47 | 12 |
Потому что параллельность только дополнительно даёт нагрузку на исполняющую среду. При работе с обёрткой Emgu.CV могу посоветовать выносить код, исполняющийся долгое время, в фоновый поток (чтобы не вис поток GUI). Этого более чем достаточно.
0
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
||||||
10.10.2016, 12:08 [ТС] | 13 | |||||
У меня сегментация яблок работает очень долго. Именно сегментация яблок, а не их выделение из фона. Вот пример сегментации.
Автоматически я определяю число сегментов, из которых яблоки состоят. вот таким вот образом я определяю:
а хотелось бы каждое яблоко обрабатывать отдельно в своем потоке на отдельном ядре
0
|
.NET senior
440 / 358 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
|
10.10.2016, 12:10 | 14 |
Dimarik__1, скиньте изображение, которое анализируете - попробую прокрутить его в своём тесте и скажу, сколько это занимает по времени.
0
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
|
10.10.2016, 12:14 [ТС] | 15 |
Вот изображение. Но проблема именно в сегментации. Это самый медленный кусок. Алгоритм сегментации сам разрабатывал для своих задач. Каждое яблоко сегментируется отдельно независимо от другого. Это логично их распараллелить чтобы ускорить выполнение кода. Но в результате все только хуже работает после параллельности. График загрузки процессоров показывает что все загружено (через диспетчер задач), но тем не менее скорости не прибавляется
0
|
.NET senior
440 / 358 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
||||||
10.10.2016, 12:45 | 16 | |||||
Dimarik__1, максимум, чего удалось добиться мне - обнаружить 9 яблок из 14. Картинка во вложении.
Код: Кликните здесь для просмотра всего текста
Тест всё так же успешно отрабатывает примерно за 1 секунду. Попробуйте в предложенном коде динамически поиграться с параметрами param1 и param2 метода HoughCircles (пороговые значения обнаружения границ на изображении) для достижения максимально высокого качества обнаружения.
0
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
|||||||||||||||||||||||||||||||
10.10.2016, 15:19 [ТС] | 17 | ||||||||||||||||||||||||||||||
я же говорю. у меня не проблема в том чтобы единичные объекты выделить. Мне надо их сегментировать по своему алгоритму для своих задач. Каждый объект отдельно надо разбить на сегменты. Так вот. Эта сегментация работает с каждым объектом по-отдельности. и мне надо распараллелить. а у меня тормоза при распараллеливании сегментации. А не при выделении единичных объектов
Добавлено через 2 часа 28 минут Решил проверить, каким за сколько времени обрабатывается картинка на разном числе потоков: 1. Получаю картинку и вызываю функцию обработки:
Когда я пишу:
если же я напишу цикл вот так:
0
|
10.10.2016, 19:40 | 18 | ||||||||||
Сообщение было отмечено Dimarik__1 как решение
Решение
Dimarik__1,
Смотрите, у вас незначительные на первый взгляд проблемы накапливаются и приводят к тому что вы имеете. 1) Код сложный и запутанный. Например один метод OneObject - 193 строки невнятных вычислений. 193 строки! Are you seriously? Считается хорошим тоном иметь не более 30 строк в методе. (ну и кроме того, наименование метода OneObject - неправильное) 2) У вас подозрительно много вызовов GC.Collect(). Это наталкивает на нехорошие мысли: во-первых, потому что явный вызов GC.Collect() - обычно не требуется и не приветствуется, как вредный для здоровья, во-вторых, это пахнет тем, что у вас идет перерасход памяти и вы пытаетесь его "починить" вызовом GC.Collect(). 3) И точно. При запуске расчетов, видно, что у вас расход памяти программой идет на сотни мегабайт, в то время как решается довольно простая задача, и совершенно непонятно зачем там столько памяти. Почему? Потому что вы очень неоптимально используете память. Давайте посмотрим на вот этот метод: Кликните здесь для просмотра всего текста
Вы создаете массив double размером 256 * 256 * 256. Только этот массив займет в памяти минимум 134 MB! И главное зачем он? Вы всего лишь пытаетесь посчитать энтропию? С ценой 134MB? OMG. Ведь есть же Dictionary<>, и ваш метод можно переписать вот так с малым (относительно) расходом памяти (и который кстати будет работать на порядки быстрее, поскольку в нем нет трехэтажных вложенных циклов): Кликните здесь для просмотра всего текста
Остальные методы вероятно примерно такие-же. 4) И теперь, отвечая непосредственно на ваш вопрос, почему у вас многопоточная версия работает медленнее однопоточной. А это потому, что у вас приложение тратит время не на расчеты. Оно тратит основное время на выделения/освобождения памяти. А поскольку память вы выделяете под каждый поток отдельно, то и получается, что чем больше потоков, тем пропорционально больше памяти используется, и тем больше времени занимает работа программы. Оптимизируйте программу, особенно по памяти и все будет хорошо.
4
|
0 / 0 / 1
Регистрация: 27.12.2014
Сообщений: 298
|
||||||
10.10.2016, 20:05 [ТС] | 19 | |||||
Спасибо. Очень понятно ответили. С памятью буду разбираться.Но есть ещё 1 вопрос:
1. Вот у меня имеется цикл по потокам, где я хочу оценить, за какое время у меня отработает алгоритм при разном распараллеливании:
то при i = 1 отработает за 132 сек, при i = 2 за 138, при i = 3 за 156. А если я напишу for (int i = 2; i <= iThreadsMax; i++) то при i = 2 отработает за 75 секунд. Как это может быть объяснено? Ведь память уже очищена первым операторов в цикле и внутри она нигде дополнительно не очищается. или очищается?
0
|
.NET senior
440 / 358 / 137
Регистрация: 23.09.2016
Сообщений: 980
|
|
10.10.2016, 22:10 | 20 |
Dimarik__1, это очень глубокое заблуждение. При вызове GC.Collect память вот так с пол-пинка магическим образом не освобождается. Скорее это можно интерпретировать как "уважаемый Сборщик Мусора, пожалуйста, когда ты в ближайшее время будешь свободен, попробуй освободить хотя бы немножко памяти среди этой кучи байт".
0
|
10.10.2016, 22:10 | |
10.10.2016, 22:10 | |
Помогаю со студенческими работами здесь
20
Параллельное программирование - слишком большое ускорение Параллельное программирование для ускорения обработки информации Параллельное программирование:Построить вектор, элементы которого равны произведению соответствующих элементов Вычислить евклидову норма вектора. Используя класс Task или Parallel. Параллельное программирование Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |