Forums » Программное обеспечение »
Программирование на ассемблере. Пара вопросов о производительности
Added by qewerty over 11 years ago
Вот допустим есть функция перемножения матриц 4 на 4 (указатели на стек и фрейм не меняются, т.к. локальные переменные на стеке не нужны). Матрицы хранятся по столбцам (как в OpenGL).
.global qf_mat44_mul qf_mat44_mul: .alias qf_mat44_mul.a #SP,4 .alias qf_mat44_mul.b #SP,8 .alias qf_mat44_mul.c #SP,12 jmp qf_mat44_mul.P0 ; сохранение адресов аргументов в регистрах rdl qf_mat44_mul.a setl #32, @1 rdl qf_mat44_mul.b setl #33, @1 rdl qf_mat44_mul.c setl #34, @1 complete .local qf_mat44_mul.P0 qf_mat44_mul.P0: rdl #SP jmp @1 ; чтение матрицы b va01 := rdq #32 va23 := rdq #32,8 va45 := rdq #32,16 va67 := rdq #32,24 va89 := rdq #32,32 vaAB := rdq #32,40 vaCD := rdq #32,48 vaEF := rdq #32,56 ; вспомогательные значения, для упаковки матрицы a в строки va54 := pack @va45, @va45 vaDC := pack @vaCD, @vaCD va76 := pack @va67, @va67 vaFE := pack @vaEF, @vaEF ; упаковка строк матрицы a va04 := patch @va45, @va01 va8C := patch @vaCD, @va89 va15 := pack @va54, @va01 va9D := pack @vaDC, @va89 va26 := patch @va67, @va23 vaAE := patch @vaEF, @vaAB va37 := pack @va76, @va23 vaBF := pack @vaFE, @vaAB ; чтение матрицы b vb01 := rdq #33 vb23 := rdq #33,8 vb45 := rdq #33,16 vb67 := rdq #33,24 vb89 := rdq #33,32 vbAB := rdq #33,40 vbCD := rdq #33,48 vbEF := rdq #33,56 ; скалярные произведения строк матрицы a со стобцами матрицы b madd @va04, @vb01 madd @va8C, @vb23 vc_0 := addf @1, @2 madd @va15, @vb01 madd @va9D, @vb23 vc_1 := addf @1, @2 madd @va26, @vb01 madd @vaAE, @vb23 vc_2 := addf @1, @2 madd @va37, @vb01 madd @vaBF, @vb23 vc_3 := addf @1, @2 ; -- madd @va04, @vb45 madd @va8C, @vb67 vc_4 := addf @1, @2 madd @va15, @vb45 madd @va9D, @vb67 vc_5 := addf @1, @2 madd @va26, @vb45 madd @vaAE, @vb67 vc_6 := addf @1, @2 madd @va37, @vb45 madd @vaBF, @vb67 vc_7 := addf @1, @2 ; -- madd @va04, @vb89 madd @va8C, @vbAB vc_8 := addf @1, @2 madd @va15, @vb89 madd @va9D, @vbAB vc_9 := addf @1, @2 madd @va26, @vb89 madd @vaAE, @vbAB vc_A := addf @1, @2 madd @va37, @vb89 madd @vaBF, @vbAB vc_B := addf @1, @2 ; -- madd @va04, @vbCD madd @va8C, @vbEF vc_C := addf @1, @2 madd @va15, @vbCD madd @va9D, @vbEF vc_D := addf @1, @2 madd @va26, @vbCD madd @vaAE, @vbEF vc_E := addf @1, @2 madd @va37, @vbCD madd @vaBF, @vbEF vc_F := addf @1, @2 ; упаковка результатов vc01 := patch @vc_1, @vc_0 vc23 := patch @vc_3, @vc_2 vc45 := patch @vc_5, @vc_4 vc67 := patch @vc_7, @vc_6 vc89 := patch @vc_9, @vc_8 vcAB := patch @vc_B, @vc_A vcCD := patch @vc_D, @vc_C vcEF := patch @vc_F, @vc_E ; запись результатов wrq @vc01, #34 wrq @vc23, #34,8 wrq @vc45, #34,16 wrq @vc67, #34,24 wrq @vc89, #34,32 wrq @vcAB, #34,40 wrq @vcCD, #34,48 wrq @vcEF, #34,56 complete
Есть кой-какие вопросы о том, как сделать её максимально быстрой:
1.) Имеет ли смысл сохранять адреса аргументов в индексных регистрах для дальнейшего использования?
Т.е. сделав:
rdl qf_mat44_mul.a setl #32, @1
Далее можно загрузить матрицу так:
va01 := rdq #32 va23 := rdq #32,8 va45 := rdq #32,16 va67 := rdq #32,24 va89 := rdq #32,32 vaAB := rdq #32,40 vaCD := rdq #32,48 vaEF := rdq #32,56
Вместо того, чтобы читать адрес в коммутатор и вычислять адреса вот так:
pa01 := rdl qf_mat44_mul.a pa23 := addl @pa01, 8 pa45 := addl @pa01, 16 pa67 := addl @pa01, 24 pa89 := addl @pa01, 32 paAB := addl @pa01, 40 paCD := addl @pa01, 48 paEF := addl @pa01, 56 va01 := rdq @pa01 va23 := rdq @pa23 va45 := rdq @pa45 va67 := rdq @pa67 va89 := rdq @pa89 vaAB := rdq @paAB vaCD := rdq @paCD vaEF := rdq @paEF
Но последнее позволяет реализовать функцию одним параграфом. Т.е. меня интересует есть ли смысл избегать переключения параграфов, а также скорость выполнения чтения из адреса в регистре со смещением и из вычисленного адреса в коммутаторе. Возможно есть какие-то подводные камни.
2.) Имеет ли смысл минимизировать кол-во операций записи в память?
Например, тут у меня сделано так:
; упаковка результатов vc01 := patch @vc_1, @vc_0 vc23 := patch @vc_3, @vc_2 vc45 := patch @vc_5, @vc_4 vc67 := patch @vc_7, @vc_6 vc89 := patch @vc_9, @vc_8 vcAB := patch @vc_B, @vc_A vcCD := patch @vc_D, @vc_C vcEF := patch @vc_F, @vc_E ; запись результатов wrq @vc01, #34 wrq @vc23, #34,8 wrq @vc45, #34,16 wrq @vc67, #34,24 wrq @vc89, #34,32 wrq @vcAB, #34,40 wrq @vcCD, #34,48 wrq @vcEF, #34,56
Но можно сделать и так:
wrl @vc_0, #34 wrl @vc_1, #34,4 wrl @vc_2, #34,8 ... wrl @vc_E, #34,56 wrl @vc_F, #34,60
Что делает 16 операций записи в память, а не 8, но все 16 операций независимы, тогда как в первом случае операции записи зависят от упаковки значений.
Replies (82)
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 11 years ago
Поправим SDK в ближайшее время. Как только будет доступна бета версия новой модели выложим и её с отладчиком, а также описание нового удобного функционала.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by sprin about 11 years ago
mouse wrote:
Файл t.c не используется в сборке — это эталон на Си под gcc. (в коде встречается множественный printf и наколенный ROL вместо одной ассемблерной инструкции).
Понятно.
mouse wrote:
gost_enc.epilogue - несколько условий перехода, которые могут одновременно быть истинными (? уточнить) (в модели возможно переход будет по последнему обработанному, а на железе неизвестно)
gost_dec.epilogue - несколько условий перехода, которые могут одновременно быть истинными (? уточнить) (в модели возможно переход будет по последнему обработанному, а на железе неизвестно)Данные условия мы пилили совместно с krufter_multiclet. Это единственный дешёвый способ перейти по нескольким условиям, не прибегая к ещё одному параграфу и повторной перепроверке условий. Условия построены таким образом, чтобы осуществить единственное возможное ветвление.
Соглашусь, что для "gost_enc.epilogue" следующий вариант вроде работает нормально:
gost_enc.epilogue¶
Show Hidegost_enc.epilogue: r1 := getl #IDX r2 := addl @r1, 1 setl #IDX, @r2 r3 := subl @r2, 24 r4 := subl @r2, 32 r5 := and @r3, 0x80000000 jne @r5, gost.load_key1_24 r6 := and @r4, 0x80000000 r7 := xor @r5, @r6 jne @r7, gost.load_key25_32 r8 := or @r5, @r7 je @r8, gost.save_results ; Готово, далее сохраняем и берём следующие значения из буфера complete
А вот для "gost_dec.epilogue" немного неправильно сделано, его надо немного модифицировать:
gost_dec.epilogue полный вариант¶
Show Hidegost_dec.epilogue: r1 := getl #IDX r2 := subl @r1, 1 setl #IDX, @r2 je @r1, gost.save_results ; Готово, далее сохраняем и берём следующие значения из буфера jne @r1, gost_dec.epilogue.2 complete gost_dec.epilogue.2: r1 := getl #IDX r2 := subl @r1, 24 r3 := subl @r1, 32 r4 := and @r2, 0x80000000 jne @r4, gost.load_key1_24 r5 := and @r3, 0x80000000 r6 := xor @r5, @r4 jne @r6, gost.load_key25_32 or @r4, @r6 ; Возможно это лишнее je gost.round ; Возможно это лишнее complete
или укороченный вариант (если последние 2 команды не нужны):
gost_dec.epilogue укороченный вариант¶
Show Hidegost_dec.epilogue: r1 := getl #IDX r2 := subl @r1, 1 setl #IDX, @r2 je @r1, gost.save_results ; Готово, далее сохраняем и берём следующие значения из буфера jne @r1, gost_dec.epilogue.2 complete gost_dec.epilogue.2: ; Убрали лишнее r1 := getl #IDX r2 := subl @r1, 24 r4 := and @r2, 0x80000000 jne @r4, gost.load_key1_24 je @r4, gost.load_key25_32 complete
Суть в том, что "gost_dec.epilogue" нельзя сделать одним параграфом. Затык был именно в том, что одновременно выполняются 2 условия. На последнем шаге (в модели): (idx < 0) и (j != 0), отсюда и получаются лишние циклы, вместо того, чтобы выйти на "save_results".
gost_2_1.asm (12.4 KB) gost_2_1.asm |
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 11 years ago
Да, gost_dec.epilogue необходимо поправить. Если немного подумать, то можно и одним параграфом сделать, просто чтобы переходы не перекрывали друг друга(т.е. 2 перехода не должно сработать в одном параграфе). Для удобства пользователей в следующих реализациях процессора подумаем над новыми командами, позволяющими упростить формирование множественных переходов в одном параграфе. Хотя и сейчас не запрещено использовать несколько переходов, которые срабатывают в разное время.
Поправить параграф предлагаю следующим образом:
gost_dec.epilogue: getl #IDX subl @1, 1 setl #IDX, @1 subl @2, 24 subl @3, 32 and @4, 0x80000000 jne @1, gost.save_results and @4, 0x80000000 subl @3, @1 js @1, gost.load_key1_24 and @6, 0x80000000 xor @1, @4 jne @1, gost.load_key25_32 complete
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 11 years ago
Переписал гост полностью на ассемблере, всё работает. Возможно ошибка в Си коде.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 11 years ago
sprin вы в числе главных претендентов на отладочную плату по конкурсу. У пользователя trott отладочная плата, насколько мне известно, имеется(хотя я могу ошибаться).
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by trott about 11 years ago
пользователь trott в отпуске до понедельника. И платы у пользователя trott нет в наличии, а нужна... асинхронным электродвигателем управлять.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 11 years ago
Хорошо, значит нужны две платы.
- « Previous
- 1
- 2
- 3
- 4
- Next »