Это мой персональный дневник. Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Конец ускоренной strlen на «Флиппере»

В итоге, эпопея с ускорением функции замера длины строки в кодировке UTF-8 на «Флиппере Зеро» подошла к концу — коммит не взяли.

У меня с самого начала этой затеи были сомнения. Я понимал, что для того, чтобы решить чью-то проблему, надо сначала доказать, что она существует, чему я должного внимания не уделил. Кроме того, сейчас в мире программирования очень важно решить проблему понятным образом, а векторное ускорение мало кому знакомо.

Тем не менее, я с удовольствием повозился инструкциями SIMD. До этого мини-проекта у меня было теоретическое понимание о том, что это за функции, но на практике я их не использовал.

Моя функция, кстати, претерпела некоторые изменения:

size_t furi_string_utf8_length(FuriString* str) {
    size_t len = string_size(str->string);
    const char * cstr = string_get_cstr(str->string);
    const char* end = cstr + len;

    if(len >= sizeof(uint8x4_t)) {
        const char* vend = end - sizeof(uint8x4_t);

        int8x4_t zero = 0x00000000;
        int8x4_t one = 0x01010101;
        int8x4_t threshold = -1077952577; // -65, -65, -65, -65

        do {
            int8x4_t vec = *(int8x4_t*)cstr;

            __ssub8(threshold, vec);
            uint8x4_t result = __sel(one, zero);

            len -= __usada8(result, zero, 0);

            cstr += sizeof(uint8x4_t);
        } while(cstr <= vend);
    }

    while(cstr < end) {
        signed char c = *cstr++;
        len -= c < -64;
    }

    return len;
}

Оказалось, что тип FuriString хранит в себе бинарную длину строки, поэтому я переделал код, чтобы он не пытался читать чужую память. В векторизованой части это было вероятно, но своих рассуждений и дискуссии по коммиту я сделал вывод, что в случае «Флиппера» это не имеет какого-либо значения.

Тем не менее, если использовать бинарную длину, код получается более аккуратным и немного упрощается, так что грех не воспользоваться. Интересно бы, кстати, измерить наивный алгоритм без векторной части, но с использованием бинарной длины, наверное займусь этим в ближайшее время.

В итоге, решая эту, возможно несуществующую, проблему, я опробовал на практике векторные инструкции расширений NEON и DSP SIMD, научился делать два параллельных запроса на вливание в «Гитхабе» и ещё раз вспомнил как компилировать и заливать свою прошивку во «Флиппер Зеро».