Тут вдруг пришло мне в голову, что Эльбрус логично сравнить с SIMD блоками процессоров AMD SSE/ARM NEON.
Сравним вот такой кусок кода:
Этот кусок кода переводит grayscale 8 бит на пиксель картинку в однобитную картинку. Т.е. 8 байт на входе преобразуются в 1 байт на выходе, берутся только старшие биты от каждого байта.
gcc при компиляции с флагом -O3 генерирует какой-то код для sse/neon. Если компилировать с флагом -Os то генерирует код на обычных целочисленных регистрах.
Ещё у меня завалялся код скопированный со StackOverflow, который делает ту-же операцию на neon, но написанный человеком.
Так что будем сравнивать 3 платформы.
1 - AMD Rysen 5 3600 (4126 MHz)
2 - Cortex-A7 (Maix III armv7-a 800 MHz)
3 - Elbrus (Elbrus-8C, 1200 MHz)
Прежде всего о размерах кода.
PlatformTime
AMD -O3 784 байта
AMD -Os 133 байта
Cortex-A7 -O3 678 байт
Cortex-A7 -Os 106 байт
Cortex-A7 Human neon 98 байт
Elbrus -O3 1104 байт
*Human neon - это код, который написан человеком. Он самый оптимальный по размерам, и обрабатывает сразу по 128 байт. Причем человек хитрое животное, автор извернулся и написал код, который не требует, что-бы size был кратен 128 байтам. Достаточно кратности 8-ми байтам.
*Для Эльбрус опции -O3 и -Os генерируют одинаковый по размеру и скорости код.
В предыдущих постах объём кода генерируемого для Elbrus мне казался огромным, в сравнению с кодом для процессора. Но вот если сравнивать с кодом генерируемым для SIMD варианта, то он уже лишь "немного больше, чем на остальных платформах".
Теперь о производительности. (size = 256*864 = 216 КБ)
PlatformTimeTakts per byte
AMD -O3 15 us0.28
AMD -Os 150 us2.8
Cortex-A7 -O3 360 us1.3
Cortex-A7 -Os 1617 us5.8
Cortex-A7 Human neon 177 us0.64
Elbrus -O3 70 us0.37
Пара мыслей.
Писать на ASM всё ещё есть смысл, хотя и редко. Под AMD код отлично векторизовался и не уверен, что человек лучше напишет. Под Cortex-A7 человеческий код двухкратно быстрее, чем сгенерированный gcc. И заодно в 6 раз меньше. Слова __restrict__ и __builtin_assume_aligned имеет смысл писать. __builtin_assume_aligned немного уменьшает количество генерируемого кода.
Elbrus медленнее, чем AMD примерно пропорционально своей тактовой частоте. Но на этой задаче Elbrus сильно быстрее, чем Cortex-A7.
Вобщем народ постарался, очень постарался, что-бы Эльбрус работал за разумное время.
И вот кстати пара мыслей, чего не хватает в современных языках программирования (и немного в asm не хватает).
Первое - не хватает saturated арифметики. Т.е. что-бы был какой-то тип uint8s_t для которого 200+200 = 255, а соотвественно 100-200=0.
Второе - нет swizzle. Т.е. это операция, которая берёт 2 входных операнда uint8_t и делает из них uint16_t в котором битики первого и второго операнда чередуются. Это одна из базовых для оптимального использования кеша процессора для двухмерных массивов. Но к сожалению на процессоры её "не завезли".