![]() |
Модераторы: LSD, AntonSaburov |
![]() ![]() ![]() |
|
x8m6 |
|
||||||||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 156 Регистрация: 11.12.2008 Репутация: нет Всего: нет |
В общем есть один итерационный метод , с помощью которого решаются системы линейных алгебраических уравнений. Этот метод называется методом сопряженных градиентов (может кто слышал).
Чтобы было понятно приведу сразу его код (последовательный алгоритм): Класс самого метода
И класс матрично - векторных операций, без которых не обойтись
Вообщем как он работает вкратце: Есть матрица A , вектор b и нужно решить систему A*x = b. Т.е. найти вектор x. Вектор x находится последовательными приближениями. В начальном (нулевом) приближении x - нулевой. Основной цикл алгоритма (шаг 4 - шаг 8) И каждый раз на каждой итерации x уточняется, пока не придет к искомому результату. Точность проверяется по невязке (см. шаг 7) и параметру eps . Метод строит последовательность направлений спуска (вектор z ). Находится коэффициент alpha и по этому коэффициенту уточняется решение (вектор x). Если решение в этом случае не достигло заданной точности, то направления подправляются коэффициентом beta и процедура повторяется. Пример :
При n = 100 метод решает за 176 итераций. (20 секунд по времени) Добавлено @ 14:45 Теперь нужно реализовать всё это в многопоточном виде. Основными операциями метода (в главном цикле) являются : 1. Умножение матрицы на вектор ( 1 раз); 2. Скалярное произведение векторов (3 раза); 3. Умножение вектора на число и сложение его с другим вектором (операция saxpy) (3 раза) Чтобы создать многопоточную версию метода нужно лишь их реализовать в параллельном виде. Благо данные операции очень легко поддаются распараллеливанию. Например нужно умножить матрицу на вектор в параллельном виде. Каждый поток обрабатывает свою часть матрицы (количество строк) и вектора (элементов). Матрица разбивается на полоски. Делается это построчно. Это так называемый ленточный подход. ![]() Допустим есть матрица 10x10 и 2 потока. В этом случае 1-ый поток обрабатывает с 1 по 5 -ую строчку матрицы. 2-ой поток с 6-ой по 10-ую. Именно поэтому в классе MatrixVectorOperations все методы имеют два входных параметра begin и end. Чтобы каждый поток мог вызвать метод и указать ему какую часть матрицы (и/или вектора) обрабатывать. Ну а теперь то, зачем собственно и была создана эта тема и было приведено выше описание - многопоточная версия алгоритма.
Добавлено @ 14:48 Ну и конечно класс поток:
Добавлено через 10 минут и 13 секунд Когда нужно выполнить какую- нибудь операцию (будь то умножение матрицы на вектор или произведение веторов или др.) всем потокам задается соответсвующий режим и вызывается для каждого потока метод resume(), который вызывает в себе notify() и пробуждает поток. Каждый поток выполняет операцию, попадает в синхронизированный блок и засыпает вновь. Пока все вычислительные потоки не заснут главный поток не должен ничего делать (т.е пока какая - либо операция полностью не завершится на всех потоках к следующей операции переходить нельзя), поэтому для главного потока него вызывается метод sleep(). Уже при n = 100 выполняется очень долго (около 100 секунд). Причем практически не загружает процессор (при выполнении загрузка процессора 0-1%). Первый же метод (последовотельный) алгоритм загружает процессор как и должен на 50%, так как используется одно ядро. Что то тут не так. При 2-ух потоках должен загружать машину (2-ух ядерный процессор) на 100%. Не могу разобратся что сделал не так. Вообще нужно сделать как можно эффективнее. Как по другому реализовать работу потоков не знаю. Вообщем нужна ваша помошь дорогие гуру. Это сообщение отредактировал(а) x8m6 - 11.12.2008, 14:53 |
||||||||||
|
|||||||||||
anonymouse |
|
|||
Бывалый ![]() Профиль Группа: Участник Сообщений: 197 Регистрация: 18.8.2004 Репутация: нет Всего: 1 |
Ну во первых кто вам сказал, что Java процессы будут распределяться равномерно на ваши процессоры.
Во вторых, попробуйте абстрагироваться и убрать все ваше описание задачи и сделать схему работы потоков. Я не очень вникал в задачу, но я не уверен что вам нужна многопоточность в данном случае. Ведь если процессы запускать параллельно то это еще не значит что все будет работать быстрее. Паралельность как правило требуется когда есть прерывания, когда процессор в связи со спецификой задачи простаивает. В третих есть еще такая вещь как volatile для работы одним обьектом во многих потоках. Это чтобы не заморачиваться с wait и notify Это сообщение отредактировал(а) anonymouse - 11.12.2008, 22:38 --------------------
Много чего интересного... |
|||
|
||||
x8m6 |
|
||||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 156 Регистрация: 11.12.2008 Репутация: нет Всего: нет |
Все зависит от самих процессов. Если алгоритм построен так, что при нем параллельные вычисления равномерно распределены по потокам, то JVM обязана их распределить равномерно по процессорам. ( в данном случае по ядрам).
Как раз таки в этом случае и нужна. Специфика этого алгоритма такова что при параллельном запуске он должен работать быстрее.
Как раз таки процессор и простаивает. (точнее не процессор а одно ядро процессора, в тот момент когда 2-ое нагружено полностью - но это при последовательном алгоритме). Цель данной разработки именно использовать возможности современных многоядерных процессоров полностью, воспользовавшись встроенной многопоточностью в Java. Ещё раз повторяю алгоритм должен хорошо распараллеливаться. Посмотрите например здесь http://www.intuit.ru/department/calculate/paralltp/8/5.html Это сообщение отредактировал(а) x8m6 - 11.12.2008, 23:17 |
||||||
|
|||||||
SoulKeeper |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 375 Регистрация: 14.1.2007 Где: Ukraine, Lviv. Репутация: 11 Всего: 15 |
Судя по картинке - сойдет что-то такое:
Тут нагрузка будет распределена на все доступные ядра процессора (ну или если количество єлементов меньше чем ядер, то вся матрица будет обрабатываться параллельно), поток будет брать следующий доступный рядок из матрицы и делать с ним то что будет написано вместо // TODO: Here we should do all work with matrix row Но честно говоря я ничего с Вашей математики не понял ![]() Это сообщение отредактировал(а) SoulKeeper - 12.12.2008, 02:01 |
|||
|
||||
x8m6 |
|
||||||
Бывалый ![]() Профиль Группа: Участник Сообщений: 156 Регистрация: 11.12.2008 Репутация: нет Всего: нет |
Все это конечно замечательно, но это не совсем то что мне надо. например мне нужно умножить матрицу на вектор:
result - это ещё один вектор класса ConjugateGradient. В этом случае матрица "matrix" будет умножатся на вектор "vector" и результат будет записываться в вектор "result". В вашем случае, после того как матрица будет полностью обработана потоки завершатся. А мне нужно умножать матрицу на вектор в цикле (посмотрите пожалуйста внимательно ещё раз главный цикл шаг 4- шаг 8). do { q = A*z; while(); Поэтому чтобы в цикле каждый раз заново не создавать потоки (что не есть good), после умножения я их приостанавливаю а на следующей итерации цикла перезапускаю. В вашем случае после умножения они все завершаются и чтобы на следующей итерации вновь произвести умножение нужно опять их создать. Тем более что кроме умножения матрицы вектор в главном цикле ещё 3 операции произведения векторов и 3 операции saxpy. В вашем случае придется на каждой итерации главного цикла создавать [кол-во процессоров]*7 разных потоков. В конце итерации убивать их и на следующей итерации опять создавать. А это не очень хорошо повлияет на производительность. Поэтому я и решил создать потоки всего один раз (ещё до начала вычислений) и уже в процессе вычислений управлять ими (назначая им режим работы - mode, и приостанавливая и перезапуская их когда нужно). Именно с приостановкой и перезапуском потоков возникают какие - то проблемы, поэтому и процессор всё время простаивает.
Спрашивайте что не понятно я вам объясню. |
||||||
|
|||||||
Vurn |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 51 Регистрация: 24.5.2007 Репутация: 2 Всего: 3 |
Ответил в javatalks.ru
|
|||
|
||||
![]() ![]() ![]() |
Правила форума "Java" | |
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Java: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |