Project

General

Profile

Программирование на ассемблере. Пара вопросов о производительности

Added by qewerty over 6 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 over 6 years ago

Поправим SDK в ближайшее время. Как только будет доступна бета версия новой модели выложим и её с отладчиком, а также описание нового удобного функционала.

RE: Программирование на ассемблере. Пара вопросов о производительности - Added by sprin over 6 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


А вот для "gost_dec.epilogue" немного неправильно сделано, его надо немного модифицировать:

gost_dec.epilogue полный вариант

Show

или укороченный вариант (если последние 2 команды не нужны):

gost_dec.epilogue укороченный вариант

Show

Суть в том, что "gost_dec.epilogue" нельзя сделать одним параграфом. Затык был именно в том, что одновременно выполняются 2 условия. На последнем шаге (в модели): (idx < 0) и (j != 0), отсюда и получаются лишние циклы, вместо того, чтобы выйти на "save_results".

RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet over 6 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 6 years ago

Переписал гост полностью на ассемблере, всё работает. Возможно ошибка в Си коде.

RE: Программирование на ассемблере. Пара вопросов о производительности - Added by krufter_multiclet about 6 years ago

sprin вы в числе главных претендентов на отладочную плату по конкурсу. У пользователя trott отладочная плата, насколько мне известно, имеется(хотя я могу ошибаться).

RE: Программирование на ассемблере. Пара вопросов о производительности - Added by trott about 6 years ago

пользователь trott в отпуске до понедельника. И платы у пользователя trott нет в наличии, а нужна... асинхронным электродвигателем управлять.

(76-82/82)