Pull to refresh

Comments 17

В подобных упражнениях намного важне и сложнее написать правильный бенчмарк, чем собственно сам код, который меряет что-либо.
Современные компиляторы очень сложны в своих оптимизациях, при этом могут случаться парадоксальные на первый взгляд вещи, когда -o2 работает медленнее -o1 и тому подобные чудеса с -o3/-oX. И это только в рамках одной версии gcc.
Тем более глубокой становится кроличья нора, если захотеть мерять разные платформы с архитектурами под одну гребёнку.
Всякие прогревы кэшей и т.п. можно уже и не вспоминать.

Код бенчмарка был позаимствован у abseil — хочется верить, что ребята разбираются.

Ну тут есть ряд стандартных приёмов. Излишняя оптимизация на работе с некоторыми переменными устраняется установкой volatile на них. Влияние прогрева кэша данных лечится мерами типа: массив на миллион входных значений преобразуется в цикле в массив в миллион выходных строк; кода — выполнить на каждой итерации ещё какое-то действие (толстое, но стороннее). И так далее.
Против хитрых эффектов оптимизаций — надо приводить результаты за все базовые уровни. Ну и заглянуть таки в ассемблерник, проверить, нет ни там неожиданных безумий.
А потом — мерять и мерять :)

Именно.
Претензий к собственно коду от abseil нет, возникает вопрос что же он на самом деле меряет.

Вряд-ли данная операция, на современных платформах, будет узком местом в какой либо программе. Интереснее и полезнее оптимизация свёртки, DCT, умножения матриц и тд. То есть то что связано с обработкой изображений. А вывод текста уже лет примерно 20 не bottleneck в процессоре.
Не знаю, как оно на самом деле, все же, Ruy свой аплгоритм выпустил в 2018 году, и вроде, даже в springer! Моя цель, это рассказывать скорее о интересном, под новым углом.
Конкретно конвертация числа в текст, может, и не требует особого ускорения, однако, если я правильно понимаю, потобные трюки позволяют ускорить конвертацию числа из одной системы счисления в другую, что уже представляет интерес для задач в теории чисел (например, для вычисления биномиальных коэффициентов по модулю простого числа)
И что изменится, если Вы будете считать остатки в 10 раз медленнее или в 10 раз быстрее? Вот допустим DCT — разница в скорости даст вам возможность экономить батарею на телефоне при просмотре видео или использовать менее мощный процессор. От свёртки в кольце вычетов по модулю простого числа на современных процессорах давно отказались, дешевле делать свертку в комплексных числах, так что не знаю…
Если Вы имеете в виду Number theoretic transform, то, возможно, в обработке изображений его не используют. Но, насколько я знаю, это самый быстрый способ перемножить два многочлена с целыми коэффициентами или два целых числа произвольной разрядности, и это имеет приложения, например, в криптографии. И научные статьи о низкоуровневых оптимизациях этого метода регулярно появляются, например, Speeding up the Number Theoretic Transform for Faster Ideal Lattice-Based Cryptography.
Там несколько другая задача, так как считаются остатки не обязательно по модулю простого числа, но кроме практических задач есть еще и научные, и для решения некоторых задач приходится перебирать большие диапазоны чисел, поэтому
>что изменится, если Вы будете считать остатки в 10 раз медленнее или в 10 раз быстрее?
от этого может зависить, напишете вы научную статью через месяц или через год!
Если Вы имеете в виду Number theoretic transform

Ну да, именно его и имел в ввиду. Там было простое число 2^2^4+1 = 65537 на которое удобно умножать ((x<<16)+x).

это самый быстрый способ перемножить два многочлена с целыми коэффициентами или два целых числа произвольной разрядности

Насколько я знаю, на базе свертки с помощью обычного, комплексного FFT, все таки быстрее.
напишете вы научную статью через месяц или через год!

Хм… Будет время подумать?
а там не будет потери точности из-за перехода от целых чисел к дробным и обратно к целым?
Будет, но оно обходится. Правда не бесплатно. И Да Вы правы, в 2019 нашли хороший способ использовать именно Number theoretic transform для этого опять. Не уследил. Спираль истории :)
Год назад упражнялся в похожей задаче, только наоборот — из огромного JSON парсил числа. Очень тривиальная реализация + одна тривиальная оптимизация, без расчехления профайлера и попыток что-либо изобрести, сразу показала скорость обработки 2000 Мбайт/с, т. е. читать с такой скоростью можно только с быстрого NVME SSD. И это был всего один поток. Дальнейшие оптимизации были нецелесообразны — негде брать данные с такой скоростью :)
uint32_t parse_32(char *str)
{
  uint32_t a;
  memcpy( &a, str, 4);
  a = (a & 0x0F0F0F0F) * 2561 >> 8;
  a = (a & 0x00FF00FF) * 6553601 >> 16;
  return a;
}

Это известный трюк?

UPD: А не работает ж, как надо. Но в целом, идея этого метода, она позаимствована из уже существующего алгоритма?
работает примерно так:
str="9630"
0) a=0x30333639
1) a=0x1E3F60
2) a=0x259E или искомые 9630

str="1876"
0) a=0x36373831
1) a=0x5712
2) a=0x754 или искомые 1876

я брал вроде бы отсюда — ссылка, в проекте используется 64битная версия для быстрого парсинга таймстэмпов.
Ну да, если 4 символа в строке, то все хорошо, а если меньше — нет. Скажем, если 1.
Sign up to leave a comment.

Articles