Можно ли оптимизировать код? - Assembler
Формулировка задачи:
День добрый!
Задача: есть полубайтовые значения - машина выдает данные от 1 до 15. Хранятся и передаются они в упакованном виде, по два значения в байте, в виде массива байт. Т.е. ar[i]:= value[i*2] + 16*value[i*2+1].
Данных много, поиск по ним - наиболее часто требуемая функция, поэтому хочется написать её на ассемблере (основной пакет - на Delphi). Задача гоняется в 64-битной среде, поэтому функция написана для x64. Привожу функцию поиска для трёх идущих подряд значений. Писал сам Наверняка можно оптимизировать, приоритет - оптимизация по времени исполнения. Взгляните, пожалуйста, ткните носом, где можно ускорить. Может, можно использовать, например, SIMD для одновременного поиска двух подряд масок?
type ByteArray = array of byte; function Search4Word(ba:ByteArray; mask:word):int64; // mask = $F000 + требуемые нам упакованные три величины asm mov bx, dx // дублируем маску rol dx, 4 // и сразу же её сдвигаем xor r10,r10 // счётчик mov r9,[rcx-8] // сохраняем количество байтов в байтовом массиве dec r9 //мы сравниваем байты со словом с шагом в один байт, таких сравнений будет length - 1, поэтому сразу уменьшаем счётчик на 1 @loop: mov ax, [rcx] // загрузка байта push ax // сохраняем для ещё одной проверки or ax, $F000 // накладываем маску cmp bx, ax // сравниваем pop ax // восстанавливаем AX jne @not_found shl r10, 1 // Нашли! Умножаем на 2, указывая адрес в "полубайтах" mov rax, r10 ret @not_found: or ax, $000F cmp dx, ax jne @not_found_ror shl r10, 1 // Нашли! Умножаем на 2, указывая адрес в "полубайтах" inc r10 // и увеличиваем на 1 - был сдвиг mov rax, r10 ret @not_found_ror: // Не нашли, циклим inc rcx inc r10 cmp r10, r9 jne @loop mov rax, - 1 // возвращаем "-1": ничего не нашли ret end;
Решение задачи: «Можно ли оптимизировать код?»
textual
Листинг программы
#include "stdafx.h" #include <nmmintrin.h> int main() { __m128i a = _mm_load_si128((__m128i*)"456 "); __m128i b = _mm_load_si128((__m128i*)"ssss456yyyyyyyyy"); int result = _mm_cmpestri(a, 3, b, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ORDERED); //ответ 4 return 0; }
Объяснение кода листинга программы
- Подключение необходимых заголовочных файлов.
- Объявление функции main.
- Загрузка первых 4 байт из памяти в переменную a.
- Загрузка следующих 16 байт из памяти в переменную b.
- Выполнение сравнения двух строк с использованием SSE инструкции _mm_cmpestri.
- Результат сравнения сохраняется в переменной result.
- Возврат 0 из функции main, что означает успешный конец работы программы.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д