Большая матричная инверсия
Я рассматриваю обратную сторону большой матрицы с общим размером 1000 х 1000, но иногда превышает 100000 х 100000 (что в настоящее время не удается из-за времени и памяти). Я знаю, что нормальное чувство - "не принимать обратное, найти какой-то другой способ сделать это", но на данный момент это невозможно. Причина этого связана с использованием уже сделанного программного обеспечения, которое ожидает получить обратную матрицу. (Примечание: я ищу способы изменить это, но это займет много времени)
В настоящее время мы используем метод декомпозиции LU из числовых recopies, и в настоящее время я тестирую собственную библиотеку. Собственная библиотека кажется более стабильной и немного быстрее, но я все еще на стадии тестирования для точности. Я быстро просмотрел другие библиотеки, такие как ATLAS и LAPACK, но пока не провел никаких существенных испытаний.
Кажется, что собственная библиотека не использует параллельные методы для вычисления обратного (хотя и для части факторизации LU инверсии), и насколько я могу сказать, ATLAS и LAPACK аналогичны в этом ограничении. (В настоящее время я тестирую разницу скоростей для собственных с помощью openMP и без.)
Первый вопрос: может ли кто-нибудь объяснить, как можно было бы оптимизировать инверсию матрицы путем распараллеливания. Я нашел статью здесь, в которой говорится о параллельных алгоритмах инверсии матриц, но я не понял. Кажется, эта статья говорит о другом методе? Я также не уверен, полезны ли scaLAPACK или PETSc?
Второй вопрос, я прочитал эту статью об использовании графических процессоров для повышения производительности, но я никогда не кодировал графические процессоры и поэтому понятия не имею, что пытается передать, но диаграммы внизу выглядели довольно тревожно. Как это возможно и как я могу начать реализовывать что-то вроде этого, если оно должно быть истинным.
Я также нашел эту статью, еще не успел прочитать ее, чтобы понять ее, но она кажется многообещающей, поскольку память - это текущая проблема с нашим программным обеспечением.
Любая информация об этих статьях или проблемах в целом будет очень полезной. И снова я приношу свои извинения, если этот вопрос кажется неопределенным, я постараюсь расширить его, если необходимо.
Ответы
Ответ 1
Первый вопрос: может ли кто-нибудь объяснить, как можно было бы оптимизировать инверсию матрицы путем распараллеливания.
Я бы рискнул предположить, что эта и связанные с ней темы в линейной алгебре - одна из наиболее изученных тем в параллельных вычислениях. Если вы застряли в поисках чего-то, чтобы начать читать, хорошо добрый Голуб и Ван-Кредит имеют главу по этой теме. Что касается того, что Сколапак и Домашние животные, вероятно, будут полезны, конечно, первый, вероятно, последний. Конечно, оба они зависят от MPI, но это воспринимается как должное в этой области.
Второй вопрос...
Используйте графические процессоры, если у вас их есть, и вы можете позволить себе перевести свой код в модель программирования, поддерживаемую вашими графическими процессорами. Если вы никогда не кодировали графические процессоры и не имели доступа к кластеру процессоров товарного типа, вы быстрее ускоряетесь с помощью кластера, чем путем борьбы с новой технологией.
Что касается последней статьи, на которую вы ссылаетесь, ей сейчас 10 лет в поле, которое меняется очень быстро (попробуйте найти 10-летнюю исследовательскую статью об использовании графических процессоров для инверсии матрицы). Я не могу прокомментировать его превосходство или другие атрибуты, но размер проблем, о которых вы говорите, мне кажется вполне удовлетворительным для возможностей современных кластеров для вычисления в ядре (для использования старого термина). Если ваши матрицы очень большие, они также разрежены?
Наконец, я решительно поддерживаю ваше очевидное намерение использовать существующие готовые коды, а не пытаться разработать свои собственные.
Ответ 2
100000 x 100000 - 80 ГБ при двойной точности. Вам нужна библиотека, которая поддерживает отображенные на карте матрицы на диске. Я не могу рекомендовать определенную библиотеку, и я не нашел ничего с быстрым поиском Google. Но код из Numericical Recipes, безусловно, не будет адекватным.
Ответ 3
В отношении первого вопроса (как параллелизировать вычисление обратного):
Я предполагаю, что вы вычисляете инверсию, выполняя LU-декомпозицию вашей матрицы, а затем используя декомпозицию для решения A * B = I, где A - ваша исходная матрица, B - матрица, для которой вы решаете, и я - тождество матрица. Тогда B является обратным.
Последний шаг легко параллаллизировать. Разделите свою идентификационную матрицу вдоль столбцов. Если у вас есть p-процессоры, а ваша матрица n-by-n, то каждая часть имеет n/p-столбцы и n строк. Позволяет называть части I1, I2 и т.д. На каждом процессоре решайте систему вида A * B1 = I1, это дает вам части B1, B2 и т.д., И вы можете объединить их в форму B, которая является обратной.
Ответ 4
Разделение LU на GPU может быть ~ 10 раз быстрее, чем на процессоре. Хотя это сейчас меняется, графические процессоры традиционно разрабатываются с использованием арифметики с одиночной точностью, и поэтому старая аппаратная арифметика с одиночной точностью, как правило, намного быстрее, чем арифметика с двойной точностью. Кроме того, структура ваших матриц будет сильно зависеть от требований и производительности хранилища. Редкая матрица LU decomp размером 100 000 x 100 000 является разумной проблемой для решения и не потребует много памяти.
Если вы хотите стать специалистом и не тратите много времени на обновление оборудования, я настоятельно рекомендую использовать коммерческую библиотеку. Я бы предложил инструменты CULA. У них есть как редкие, так и плотные библиотеки графических процессоров, и фактически их бесплатная библиотека предлагает SGETRF - единую (плотную) процедуру LU decomp. Вам придется заплатить за свои библиотеки с двойной точностью.
Ответ 5
Я знаю это старое сообщение, но на самом деле - OpenCL (вы загружаете соответствующий на основе вашей видеокарты) + OpenMP + Vectorization (не в том порядке) - это путь.
Во всяком случае - для меня мой опыт работы с матрицей что-то действительно связан с накладными расходами от копирования двойных двойных массивов в систему и из нее, а также для отладки или инициализации матриц с 0 до начала вычисления - особенно когда я работаю с создание .xll для использования в Excel.
Если бы я переориентировал верх -
- попробуйте сделать так, чтобы векторизовать код (Visual Studio 2012 и Intel С++ имеют autovectorization). Я не уверен в MinGW или GCC, но я думаю, что для компилятора есть флаги для анализа ваших циклов для создания правильных кодов сборки для использования вместо обычных регистров для хранения ваших данных, чтобы заполнить регистры векторов процессора. Я думаю, что Excel делает это, потому что, когда я контролировал потоки Excel при работе с их MINVERSE(), я заметил, что используется только один поток.
Я не знаю много языка ассемблера, поэтому я не знаю, как векторизовать вручную... (еще не успели изучить это, но sooooo хочу сделать это!)
- Параллелизировать с OpenMP (omp pragma) или библиотекой MPI или pthreads (parallel_for) - очень просто - но... здесь catch - я понимаю, что если ваш матричный класс полностью одинарный, в первую очередь, - тогда распараллеливание операции как многократное умножение или обратное совпадение, может быть потеряно - поскольку распараллеливание приведет к ухудшению скорости за счет инициализации или копирования или просто доступа к непараллелизированному классу матрицы.
Но... там, где помогает параллелизация, - если вы разрабатываете свой собственный матричный класс, и вы распараллеливаете его работу с конструктором (заполнение с помощью 0 и т.д.), То вычисление LU (A ^ -1) = я также будет быстрее.
Это также математически просто, чтобы оптимизировать разложение LU, а также оптимизировать обратную замену ур для специального случая идентичности. (I.e. не тратьте время на создание какой-либо идентификационной матрицы - проанализируйте, где ваш for (row = col), и оцените как функцию с 1, а остальные с 0.)
- После того, как он был распараллелен (на внешних слоях) - матричные операции, требующие элемента по элементу, могут быть отображены для вычисления с помощью GPU (SSSSSS) - сотни процессоров для вычисления элементов - избили это!. Теперь на веб-сайте ATI есть образец кода Монте-Карло - с помощью ATI OpenCL - не беспокойтесь о переносе кода на то, что использует GeForce - все, что вам нужно сделать, это перекомпилировать там.
Для 2 и 3, хотя - помните, что накладные расходы понесены, поэтому нет смысла, если вы не обрабатываете матрицы F * K * G HUGE, но я вижу 100k ^ 2? ничего себе...
Gene