|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
Опции темы | Поиск в этой теме |
15.06.2012, 08:38 | #1 |
Пользователь
Регистрация: 15.01.2012
Сообщений: 67
|
Parallel.For ничерта не ускоряет
Значит, играюсь я тут это с нейронными сетями. Два года игрался в один поток, но решил - пора, пора уже перевести их на параллельные рельсы, зря что ли четыре ядра в компьютере?
Поскольку в нейронных сетях при вычислениях для каждого конкретного нейрона в соседние нейроны заглядывать не приходится, то вот я и распараллелил циклы проходов по нейронам, используя System.Threading.Tasks.Parallel.For . Загрузка процессора стала хоть куда, если раньше один поток шпыняло по ядрам туда сюда и процессор загружался на 25-28% (т.е. поток вычисоений плюс система), то теперь больше 95%, все четыре ядра пашут, аж дым столбом. Только вот количество итераций обучения за единицу времени при этом никак не изменилось. Создаю сеть со скрытыми 100х100 нейронами, там параллель - не хочу, для каждого нейрона во второй сотне нужно провести цикл по сотне его входных связей. Но что параллельно - 5 итераций в секунду, что последовательно - 5 в секунду. Ладно бы только это, так в параллельном режиме сеть даёт отклик с ошибками, и чем больше сеть, тем больше ошибок. Выглядит так, будто бы в принципе считает правильно, но в какой-то момент формула получает какое-то неверное значение. Поток пытается обратиться к элементу другого слоя сети одновременно с другим потоком? Ну я делаю lock на нейрон, к которому теоретически может быть одновременное обращение других потоков - ничё не меняется. Вот, скажем, код прожёвывания сетью одного входного вектора: Код:
Последний раз редактировалось yaapelsinko; 15.06.2012 в 11:18. |
15.06.2012, 10:59 | #2 |
Пользователь
Регистрация: 15.01.2012
Сообщений: 67
|
Ха, блин, да это просто издевательство, а не многопоточность.
Значит, с ошибочным пересчётом сети разобрался - оказывается, надо было лочить глобальную в рамках сети переменную this.SigmaFactor - сделал объявление новой переменной внутри цикла, лочу зыс, присваиваю значение - всё, работает нормально, даже если не лочить при этом нейрон, с которого в цикле берётся выходное значение. То ли конфликтов не возникает, то ли они настолько редкие, что незаметно. Однако ж по скорости это всё - даже медленнее немного, чем в один поток. Не смотри, что процессор за 95% загружен. Ну ЧЯДНТ? Даже выставляя ограничение на степень параллельность равное 4 (не более 4 потоков одновременно) - улучшения производительности нет (а то я бы понял, если процессор перегружается 40-100 потоками и не может это всё провернуть). При этом, поскольку процессор всё же загружен на 95%, эти потоки реально работают, а не простаивают в ожидании разлочивания общего ресурса (если бы простаивали - процессор бы не нагружали). Другая распараллеленая процидурка (шаг обучения): Код:
Последний раз редактировалось yaapelsinko; 15.06.2012 в 11:18. |
15.06.2012, 11:32 | #3 |
Пользователь
Регистрация: 11.05.2012
Сообщений: 85
|
Недавно я присутствовал на крещении племянника в одном монастыре. Батюшку ждали 3 часа, а потом он ещё сподобился выдать нам проповедь. Главной темой этой проповеди было: "Весь мир и человек были созданы одновременно 8 тысяч лет назад. А наукам не верьте - все они от Лукавого". Причем, без очков было видно, что все сидящие перед ним (кроме замученных детишек, конечно) имеют как минимум по одному диплому, т.е. суть представители этих самых наук, которые от Лукавого,-бесы, другим словом.
К Вашему вопросу это имеет вот какое отношение. И я тоже ожидал от многопроцессорности гораздо большего. Почему-то в машине AS-400 с осью OS-400 это получалось неплохо, и можно было практически до бесконечности наращивать количество основных процессоров (счета), и процессоров ввода-вывода, а главное, с пользой. А вот с нашими настольными и переносными компами, оснащенными разной пробы Виндами, этого явно не произошло. Видно, дело в архитектуре, которая, как и женщина, может дать не более того, что она может дать. И никакие программные ухищрения здесь не помогут. Вот и поверишь, что все от Лукавого, по крайней мере Windows. |
15.06.2012, 13:49 | #4 |
Дружите с Linq ;)
Форумчанин
Регистрация: 15.10.2008
Сообщений: 822
|
По сути Вы работаете с один и тем же объектом в разных потоках, т.е. он лочиться, передается из потока в поток, чтобы можно было обратиться к какому-то слою.. И как это получиться быстрее, чем в одном потоке?.. нужно попробовать "нарезать" слои, после это только работать в параллели..
Не давай организму поблажки, каждый день тренируй его в шашки..
|
15.06.2012, 14:15 | #5 |
Пользователь
Регистрация: 15.01.2012
Сообщений: 67
|
Ну я же с разными полями этого объекта работаю.
Я не вижу принципиальной разницы с примером от MS - http://msdn.microsoft.com/ru-ru/library/dd460713.aspx Опять же, если бы дело было в том, что объект лочится не даёт работать другим потокам - у меня не могло бы быть полной загрузки процессора, как я понимаю. Всё, что я реально лочу в процессе пересчёта сети - это до инициализации длинного цикла (который вызывается внутри параллельного потока) лочу на время считывания одну переменную из объекта. Считываю и разлочиваю. То есть, тут больших задержек возникать не должно. В процессе расчёта взвешенной суммы лок убрал - он почему-то ни на что не виляет, ну и хорошо. То есть, циклы свободно выполняются в параллель и друг другу не мешают (теоретически, практически, я, если честно, не понимаю, почему сигму считывать без лока нельзя, а нейроны и их поля можно). В процедуре обучения там вообще всё как у микрософта в туториале. Ну только там у них массив всё ж, а у меня объект. А производительность одна и та же. |
15.06.2012, 16:25 | #6 |
Форумчанин
Регистрация: 10.02.2009
Сообщений: 815
|
Соглашусь с Скарам. А процессор нагружается в следствии того что все потоки работают практически одновременно, но благодаря lock'у выходит 1 "полезное" действие (4 потока попеременно работают над одним обьектом).
И ещё, каким способом вы обучатете сеть? Насколько я понимаю (сейчас этим 1 раз занимаюсь) процесс обучения нельзя разделить на несколько отдельных потоков, ведь каждая операция затрагивает несколько обьектов, которые во время просчета могут быть изменены другим потоком.. и получится каша |
15.06.2012, 21:52 | #7 |
Пользователь
Регистрация: 15.01.2012
Сообщений: 67
|
Говорят - http://www.albahari.com/threading/ - что A thread, while blocked, doesn't consume CPU resources.
К тому же блокировки у меня сейчас минимум, не должна она настолько влиять. Это раз. Второе, всё, что происходит внутри одного слоя нейронной сети, прекрасно распараллеливается, так как нейроны не имеют связей между собой в пределах этого слоя. Соответственно, можно заниматься просчётом хоть всех нейронов слоя одновременно, беря соответствующие необходимые значения из предыдущего или последующего слоя. |
15.06.2012, 23:49 | #8 | |
Форумчанин
Регистрация: 10.02.2009
Сообщений: 815
|
Цитата:
|
|
16.06.2012, 01:34 | #9 |
Пользователь
Регистрация: 15.01.2012
Сообщений: 67
|
...и, кстати, что касается процедуры обучения - там вообще всё в шоколаде.
Цикл распараллеливается так, что в каждом потоке свой собственный индекс i. Внутри же я запускаю цикл, который обращается в нейронам более высокого слоя, который на данным момент уже был обработан. В каждом нейроне каждый поток обращается только к своим весам (то есть, поток с i=1 - к первому элементу массива весов, с i=2 - ко второму элементу, и так далее, практически как в туториале от МС). То есть, там всё должно нормально работать. Однако вот - работать работает, да не быстрее, а даже пожалуй медленнее. |
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Микрофон ускоряет голос | Yarigk | Компьютерное железо | 2 | 05.09.2011 12:29 |
Ускоряет или нет. | _PROGRAMM_ | Софт | 5 | 24.06.2010 12:43 |