давно уже общими силами написали бы матлибу со всеми оптимизациями, но нет, каждый жмёт свои разработки, а как было бы круто видеть
GD.RU Maths и исходник под SVN'ом где-нибудь на сорсфордже.
FearOfTheDark
> эм, можешь на пальцах показать
С PFACC немного погорячился - для матриц она не очень подходит, в отличие от векторов.
Тут можно посмотреть команды:
http://www.codenet.ru/progr/optimize/3dnow.php
http://www.tommesani.com/MMXConversion.html
Вычисление для четырех первых значений:
c11 = (a11*b11) + (a12*b21) + (a13*b31) + (a14*b41); c12 = (a11*b12) + (a12*b22) + (a13*b32) + (a14*b42); c13 = (a11*b13) + (a12*b23) + (a13*b33) + (a14*b43); c14 = (a11*b14) + (a12*b24) + (a13*b34) + (a14*b44); movq MM0, [a11, a12] // MM0 = [a11, a12] movq MM1, MM0 // MM1 = [a11, a12] punpckldq MM0,MM0 // MM0 = [a11, a11] punpckhdq MM1,MM1 // MM1 = [a12, a12] movq MM2, [a13, a14] // MM0 = [a13, a14] movq MM3, MM2 // MM3 = [a13, a14] punpckldq MM2,MM2 // MM2 = [a13, a13] punpckhdq MM3,MM3 // MM3 = [a14, a14] movq MM4, [b11, b12] // MM2 = [b11, b12] movq MM5, [b13, b14] // MM2 = [b13, b14] pfmul MM4, MM0 // MM4 = [a11*b11, a11*b12] pfmul MM5, MM0 // MM5 = [a11*b13, a11*b14] movq MM6, [b21, b22] // MM3 = [b21, b22] movq MM7, [b23, b24] // MM3 = [b23, b24] pfmul MM6, MM1 // MM6 = [a12*b21, a12*b22] pfmul MM7, MM1 // MM7 = [a12*b23, a12*b24] pfadd MM4, MM6 // MM4 = [ (a11*b11) + (a12*b21), (a11*b12) + (a12*b22) ] pfadd MM5, MM7 // MM5 = [ (a11*b13) + (a12*b23), (a11*b14) + (a12*b24) ] movq MM6, [b31, b32] // MM6 = [b31, b32] movq MM7, [b33, b34] // MM7 = [b33, b34] pfmul MM6, MM2 // MM6 = [a13*b31, a13*b32] pfmul MM7, MM2 // MM7 = [a13*b33, a13*b34] pfadd MM4, MM6 // MM4 = [ (a11*b11) + (a12*b21) + (a13*b31), (a11*b12) + (a12*b22) + (a13*b32) ] pfadd MM5, MM7 // MM5 = [ (a11*b13) + (a12*b23) + (a13*b33), (a11*b14) + (a12*b24) + (a13*b34) ] movq MM6, [b41, b42] // MM6 = [b41, b42] movq MM7, [b43, b44] // MM7 = [b43, b44] pfmul MM6, MM3 // MM6 = [a14*b41, a14*b42] pfmul MM7, MM3 // MM7 = [a14*b43, a14*b44] pfadd MM4, MM6 // MM4 = [ c11, c12 ] pfadd MM5, MM7 // MM5 = [ c13, c14 ] movq [c11, c12], MM4 movq [c13, c14], MM5
Не оптимально. Можно учитывать, что значения [a11,a11] и т.д. нужно сорхранять только в одном умножении соотв. можно попробовать все вычисления (для каждой из четверок) вести в два независимых потока или с частичным перекрытием (т.е. по мере освобождения регистров MM0 - MM4 можно начать подготовку к вычислению очередных значений C и тем самым устранив возможные задержки из-за латентности выполнения команд).
Команды сгруппированы для лучшего чтения, хотя процессор вероятно их перетасует более оптимально но по хорошему надо бы смотреть что CodeAnalyst покажет.
ksacvet777
> Там наверное ещё и проверка перед операцией есть
нету
doc.
Попробовал сравнить SSE и 3dNow!, первое быстрее, где-то на 10..20%
и на AMD SSE норм пашет( тест на Athlon XP и Athlon 64 x2 )
Aldaron
> Попробовал сравнить SSE и 3dNow!, первое быстрее, где-то на 10..20%
А что сравнивалось?
doc.
тики, время выполнения
Aldaron
> тики, время выполнения
Так какой код то?
Объясняю, на пути выполнения тестов и сравнения есть несколько затык. Первое - оптимизатор, он в MSVC настолько суровый, что всю твою писанину может вобще выкинуть как негодную, предрассчитать и подставить константы. Вердикт - оптимизатор в настройках вырубить. И это, ещё играет роль время перегонки данных по шине, т.е. если каждый раз умножать разные матрицы, то на результат сильно повлияет постоянный перегон данных из оперативки в проц.
Necrys
> Вердикт - оптимизатор в настройках вырубить.
зачем же вырубать, в реальной проге тых не вырубаешь, малоли что он там наделает. А на счёт того что он может всё предрасчитать то это да, хотя можно с этим справиться добавив заведомо неизвестное значение, например я гоняю всё в таком вот цикле:
int ju=1; cin >> ju; for (int j=0; j<ju; j++) { //... }
в таком случае он не может сделать пред расчёт ))
> И это, ещё играет роль время перегонки данных по шине
ну а в проге не ушто ты множишь всё одно и тоже. Куча объектов, у каждого своя матрица.
> то на результат сильно повлияет постоянный перегон данных из оперативки в проц.
они оба в равных условиях )
-----
вот думаю, писать математику как lib или как dll.
lib бывает матерится при подключении, типа конфиликт символов
dll надо таскать с собой
Smouking
> вот думаю, писать математику как lib или как dll.
> lib бывает матерится при подключении, типа конфиликт символов
> dll надо таскать с собой
Это, инлайнов же не будет!
Necrys
инлайнов не будет это да, но вот смотри перемножение матрицы 4х4 на 3DNow занимает 137 инструкций, куда ж их столько заинлайнить то? Тем более написаны они на асме их вроде бы компилер не будет инлайнить. да и не думаю что один call и один jmp создадут большие тормоза
да вроде должен синлайнить, в результате, ну, call и jmp не создадут конечно тормозов, так же как если и вовсе не использовать никаких sse.
Smouking
> вот думаю, писать математику как lib или как dll.
как *.h
Necrys
> да вроде должен синлайнить
он вроде не анализирует асм вставки, а в ней вызывается ret, если синлайнит то будет плохо.
Smouking
> инлайнов не будет это да, но вот смотри перемножение матрицы 4х4 на 3DNow
> занимает 137 инструкций, куда ж их столько заинлайнить то? Тем более написаны
> они на асме их вроде бы компилер не будет инлайнить. да и не думаю что один
> call и один jmp создадут большие тормоза
В ряде случаев, даже большие функции приходится инлайнить, ибо как не крути, а без инлайна скорость падает.
А чтобы не быть голословным, посмотри в посте #65 исходник, и удали от туда FINLINE.
Тема в архиве.