Forums » Программное обеспечение »
Программирование на ассемблере. Пара вопросов о производительности
Added by qewerty over 12 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 12 years ago
Поправим SDK в ближайшее время. Как только будет доступна бета версия новой модели выложим и её с отладчиком, а также описание нового удобного функционала.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by sprin about 12 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 Hide
gost_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 Hide
gost_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 Hide
gost_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 12 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 12 years ago
Переписал гост полностью на ассемблере, всё работает. Возможно ошибка в Си коде.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 12 years ago
sprin вы в числе главных претендентов на отладочную плату по конкурсу. У пользователя trott отладочная плата, насколько мне известно, имеется(хотя я могу ошибаться).
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by trott about 12 years ago
пользователь trott в отпуске до понедельника. И платы у пользователя trott нет в наличии, а нужна... асинхронным электродвигателем управлять.
RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 12 years ago
Хорошо, значит нужны две платы.
- « Previous
- 1
- 2
- 3
- 4
- Next »