LINUX.ORG.RU

Оптимизация умножения матриц


0

1

Допустим мне надо посчитать Y = A X, где A небольшая (до 30х30) не разрежённая матрица. A известна на этапе компиляции, X целые, скажем по 14 бит. Также Y можно знать не совсем точно. Есть ли какой нибудь способ преобразовать матрицу A таким образом, чтобы сократить количество умножений/сложений для заданной точности Y, которая задается при компиляции?

Если все числа целые, можно попробовать реализовать умножение матриц на шаблонах.

dmfd
()
Ответ на: комментарий от dmfd

Это делается так: "переменные" засовываются в enum'ы и non-type parameters, c помощью частичной специализации можно устроить некое подобие pattern-matching'а. Циклы делаются с помощью рекурсии.

dmfd
()
Ответ на: комментарий от ebantrop

Вопрос в том, можно ли что-то выкинуть, например? В общем случае, когда про вектор совсем ничего не известно — нет.

dmfd
()
Ответ на: комментарий от MKuznetsov

можно преобразовать A в треугольник

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

ebantrop
() автор топика
Ответ на: комментарий от ebantrop

хоть сформулируй четко чего ты хочешь. Что значит «ведет себя»?

nokachi
()
Ответ на: комментарий от dmfd

Вопрос в том, можно ли что-то выкинуть, например?

Именно. Что типа разложения матрицы в ряд, которое бы выделило главные компоненты (ох, какую, право, антинаучную херню я несу).

В общем случае, когда про вектор совсем ничего не известно — нет.

Целые числа от 0 до 2^14.

ebantrop
() автор топика
Ответ на: комментарий от ebantrop

которое бы выделило главные компоненты

Таких нѣтъ. Представь, что у тебя вектор из нулей, а одна компонента 100500. Какой бы матрица не была, эта компонента вектора всегда даст "главный" вклад.

dmfd
()

Есть ли какой нибудь способ... небольшая (до 30х30) не разрежённая матрица

Нет, ибо: факторизация полезна только для разреженных матриц, а алгоритм Штрассена имеет преимущество при размерах > 64x64.

quickquest ★★★★★
()
Ответ на: комментарий от ebantrop

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

А как это для умножения-то поможет, что-то до меня не доходит. Если матрицу привести в собственный базис, то и вектор придётся туда-обратно переводить.

dmfd
()
Ответ на: комментарий от nokachi

тогда и икс надо на соответствующую матрицу домножить

нафига ? A и полученная из неё треугольная R, эквивалентны. RX считается мягко говоря быстрее чем AX.

MKuznetsov ★★★★★
()
Ответ на: комментарий от dmfd

А, хрен его знает: вдруг упростится матрица? А то и вообще к диагональному (ну или хотя бы треугольному) виду приведется?

// шучу. Тупость сморозил.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

А то и вообще к диагональному виду приведется?

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

dmfd
()
Ответ на: комментарий от dmfd

Ты не понял: если умножений на одну и ту же матрицу 100500 штук, то если ты ее приведешь к диагональному виду, ускоришь минимум в одну-полторы степени размера матрицы!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

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

Gvidon ★★★★
()
Ответ на: комментарий от Eddy_Em

Ну, если вообще все вычисления в этот базис удастся перевести, то да.

dmfd
()
Ответ на: комментарий от Eddy_Em

Кстати, не любую матрицу можно привести к диагональному виду. ЕМНИП, самый простой вид, к которому можно свести любую матрицу, - это нормальная жорданова форма

Gvidon ★★★★
()

30*30*14 = 12килобайт. На нормальном проце в кеш врезет. Главное X транспонируй перед умножением, всё летать будет.

Профилирование делал? Проблемы именно в этом умножении?

nanoolinux ★★★★
()

Большая ли матрица X? Или может быть 30х10000?

Waterlaz ★★★★★
()
Ответ на: комментарий от MKuznetsov

A и полученная из неё треугольная R, эквивалентны. RX считается мягко говоря быстрее чем AX.

Ересь. Если Rx=Ax для любых x, то R=A.

Manhunt ★★★★★
()
Ответ на: комментарий от nanoolinux

30*30*14 = 12килобайт. На нормальном проце в кеш врезет. Главное X транспонируй перед умножением, всё летать будет.

+1. Я бы тоже сосредоточился на эффективном использовании кэшей и, если нужна экстремальная скорость, на SSE. А вот и годная статейка про кэши и умножение матриц: http://www.akkadia.org/drepper/cpumemory.pdf

Manhunt ★★★★★
()

Да, походу общего рецепта нет. А жаль. Для больших матриц много чего придумали, для маленьких придется делать по-честному.

ebantrop
() автор топика
Ответ на: комментарий от nanoolinux

30*30*14 = 12килобайт.

Недавно, помню, тут был разговор на тему, а зачем 64 бита, если на самом деле приложению доступно только 48. Рассуждать можно долго, но всё равно должно быть кратно 8-ми: 30*30*16=14КБ. Ещё в кэш должен влезть сам вектор.

gag ★★★★★
()
Ответ на: комментарий от anonymous

В два «треугольника». LU-разложение называется.

количество операций останется прежним.

dikiy ★★☆☆☆
()
Ответ на: комментарий от Manhunt

A и полученная из неё треугольная R, эквивалентны. RX считается мягко говоря быстрее чем AX.

Ересь. Если Rx=Ax для любых x, то R=A.

только если det(R)!=0

dikiy ★★☆☆☆
()

SSE, наверное. И всякие операции скалярных произведений на потоки разбивать. Только не слушай активистов со Штрассеном, на 30*30 разницы не заметишь. А числа - примитивные типы или какой-то библиотеки? Если библиотека, то в ней уже должны быть оптимизированные операции.

cdshines ★★★★★
()
Ответ на: комментарий от Manhunt

не будет примера. Я не заметил слов «для любых x» :)

dikiy ★★☆☆☆
()
Ответ на: комментарий от cdshines

Это все понятно. Я знаю про MKL, OpenBLAS (бывший GotoBLAS) и Atlas. Вопрос был в том можно ли так исхитриться что бы считать не все, а только часть для известной ошибки результата.

ebantrop
() автор топика
Ответ на: комментарий от ebantrop

можно попробовать следующий прикол:

есть такая штука, как разложение Ивасавы. То есть мы разлагаем матрицу на произведение A=ODL, где O - это ортоногальная матрица, D - диагональная и L - треугольная.

тогда мы имеем O^{-1} Y = DLX. правую часть посчитать очевдно быстрее можно, ибо DL - треугольная матрица.

Y надо получать тогда с помощью решения системы линейных уравнений. вот тут и можешь развернуться. Хотя я не думаю, что ты как-то ускоришь это дело. так как у тебя не одна система уравнений, а несколько их (сколько столбцов в матрице Y).

dikiy ★★☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.