← На главную

Rust 1.98 ускорил float-код: алгебраические операторы обогнали numpy

06.08.2026 13:43 · hackernews

В Rust 1.98 появились алгебраические операторы для чисел с плавающей точкой: algebraic_add, algebraic_sub, algebraic_mul и другие. Они разрешают компилятору переставлять операции и агрессивно оптимизировать код, например использовать SIMD-инструкции. Обычные операторы так делать не позволяют: компилятор обязан сохранить точный порядок вычислений, потому что для float порядок влияет на результат. Например, 1e16 + 1.0 == 1e16, а если массив начинается с 1e16, сумма отличается от случая, когда 1e16 стоит в конце.

Из-за такой консервативности компилятор не может применять векторные инструкции там, где они меняют порядок сложения. Автор проверил на своём i7-12700K: суммирование миллиона int64 через SIMD заняло около 150 микросекунд и 0.5 инструкций на значение, а суммирование миллиона float64 — около 560 микросекунд, и ни одной SIMD-инструкции.

Новая возможность появится в Rust 1.98 (релиз 20 августа 2026), код в статье проверялся на beta-канале. Работает так: в местах, где порядок не важен, можно явно вызывать методы .algebraic_add() и подобные, а обычные + оставить там, где важна точность.

В качестве примера автор реализовал pairwise summation — тот же алгоритм, что использует numpy.sum(). Он рекурсивно делит массив пополам и складывает результаты, а для блоков меньше 128 элементов использует algebraic_add, потому что внутри блока порядок не важен. Получилось быстрее, чем np.sum: 144 микросекунды против 190, и с той же точностью (ошибка −6.0 у Rust-версии против −14.0 у NumPy; разница незначительна).

Второй пример — сумма квадратичных разностей двух массивов. С обычными операторами код выполнялся 628 микросекунд, 4.5 инструкции на значение. С algebraic_sub, algebraic_mul и algebraic_add — 371 микросекунда и 1.0 инструкция на значение, то есть вдвое быстрее.

Вывод: в численных алгоритмах полезно комбинировать строгие операторы для точности и алгебраические для скорости. Если использовать только алгебраические, компилятор может «оптимизировать» алгоритм так, что потеряется точность, ради которой он задумывался.

Читать оригинал →