LINUX.ORG.RU

Вычисление количества символов в строке

 


0

5

Задача: Без каких-либо циклов необходимо определить длину строкового представления беззнакового целого

С++11 x86_64, решение закрытое, затачивается под конкретное железо, переносимость не нужна

Пример:

1234567 -> «1234567» num_chars = 7

Текущее решение:

num_chars = log10(x) + 1;

Что не устраивает:

70 процентов латенси на кодирование числа с предварительным определением длины занимает вычисление логарифма, что мне совершенно не нравится.

Все что мне нужно, расчет по unsigned количества символов в будущей строке. Какие нибудь соображения?



Последнее исправление: beastie (всего исправлений: 2)

Ответ на: комментарий от Eddy_Em

Не пойдет, слетит branch prediction Будет хуже

westtrd
() автор топика
Ответ на: комментарий от mashina

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

Это проблема FIX, в котором строки вот такие 12=12345666\114=1222345\110=124\1

westtrd
() автор топика

Или так:

size_t get_sym_num(uint64_t N){
  if(N < 10) return 1;
  if(N < 100) return 2;
  if(N < 1000) return 3;
  if(N < 10000) return 4;
 ...
}

а то и просто так:

size_t get_sym_num(uint64_t N){
  size_t ret = 0;
  do{
    ret++;
    N /= 10;
  }while(N);
  return ret;
}

Eddy_Em ☆☆☆☆☆
()

И вообще, тебе куда надо? На микроконтроллер или на контупер?

В любом случае, если это нужно для того, чтобы тупо сделать itoa, я бы поступил просто: 1) вычисляем заранее максимальную длину текста; 2) в функции выделяем массив нужной длины; 3) заполняем его; 4) возвращаем strdup

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от westtrd

Да что ты говоришь! Первый вариант будет самым быстрым явно!

Второй вариант будет намного быстрей десятичного логарифма для double, либо таким же по скорости, как десятичный логарифм для int.

Eddy_Em ☆☆☆☆☆
()

До тех пор пока у тебя не utf8 все очень просто и понятно.

А вот с utf8 или любым другим unicode начинается интересный акт, да.

catap ★★★★★
()
Ответ на: комментарий от Eddy_Em

Это задача HFT если знаете что это такое

Нереентерабельная функция не пройдет. Аллокация на лету запрещена, даже на стеке. Стандартная библиотека в таком месте не используется вообще.

На кону наносекунды, только просьба не рассказывать про overoptimizing

westtrd
() автор топика
Ответ на: комментарий от westtrd

просьба не рассказывать про overoptimizing

Тогда расскажу про неправильную постановку задачи. Нефиг в строки пихать цифирки — это мегажирная операция (особенно если ты эти цифирки в файлик пишешь). Загоняй все в бинарном виде, а потом уже преобразуй в символы.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

На этой неправильной постановке задачи работают все торговые дески ведущих банков мира.

Я выше описал, что это FIX messaging encoding.

Строка в совершенно определенном формате потом уходит в TCP socket.

westtrd
() автор топика
Ответ на: комментарий от mashina

В общем случае, нет такой возможности или условия, что вам хватит 8 байт на значение, как минимум 15.

westtrd
() автор топика
Ответ на: комментарий от westtrd

Это задача HFT если знаете что это такое

А если не знает то уже не задача ХЕТЭЭФ? Ты слюни та собери мальца, а то я из под стола не могу вылезти, када плюсовое быдло распальцовывать начинает.

anonymous
()
Ответ на: комментарий от reprimand

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

westtrd
() автор топика
Ответ на: комментарий от anonymous

Уважаемый, распальцовками занялись вы. Несолидно по меньшей мере

westtrd
() автор топика
Ответ на: комментарий от Eddy_Em

Нарушение формата сообщения означает reject, оно стандартизировано до байта, без каких либо плюс - минус, то что я написал выше - все до последней буквы бизнес-требования, обойти их невозможно

westtrd
() автор топика
Ответ на: комментарий от westtrd

В общем случае, нет такой возможности или условия, что вам хватит 8 байт на значение, как минимум 15.

кол-во десятичных знаков ограничено сверху?

mashina ★★★★★
()
Ответ на: комментарий от mashina

Для целых нет, но можно их ограничить искусственно и сделать для исключений отдельный вызов в API, но базово там ограничение 15

westtrd
() автор топика
Ответ на: комментарий от westtrd

Тогда сам решай. По-моему, простейшим таки было бы кучу if'ов использовать либо strdup.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Применяются gcc builtins, там даже текста функции нет Думаю, что там оптимально.

За подсказку спасибо, погляжу.

westtrd
() автор топика

А это конкретное железо сильно хитрое? В SSE4.2 вон есть какие-то быстрые функции для работы со строками.

vazgen05 ★★★
()
Ответ на: комментарий от Eddy_Em

Первый вариант the best, т.к. не надо производить «дорогое» деление. Сам цикл по себе ничего не стоит, важно что делает цикл :) При этом для первого варианта можно сделать оптимизацию по частоте используемых циферек, что приведет к 1-2 сравненям в 95% случаев.

P.S. А чем ТС не устроил strlen() ?

gh0stwizard ★★★★★
()
Последнее исправление: gh0stwizard (всего исправлений: 1)

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

anonymous
()
Ответ на: комментарий от vazgen05

Проблема в том, что на разовые операции только потеря в латенси за счет загрузки в эти регистры. И тут нет массивных вычислений.

Железо - топовые Xeon E5

westtrd
() автор топика
Ответ на: комментарий от gh0stwizard

По дорогому делению - branch misprediction выйдет значительно дороже. По частоте значений - бесполезно, это могут быть и количество вагонов и цены и суммы оборота за день, тут не прокатит.

И еще, мне кажется вы не поняли, что на входе число.

westtrd
() автор топика
Ответ на: комментарий от mashina

В принципе, возможный вариант, подумаю. Но последующие трансформации дороже выйдут, скорее всего. Проблема то не только в расчетах, но и строка должна быть выдана.

westtrd
() автор топика
Ответ на: комментарий от westtrd

И еще, мне кажется вы не поняли, что на входе число.

Я думал, что можно заинланить как-то.

ИМХО, первый вариант Eddy_Em можно переписать так, что все будет красиво и чики-пуки в виде цикла, просто создать ассоциативный массив (или подобие), забить его числами и просто по нему бегать. Заполнить его можно скриптом каким-нить, и при этом сама проверка в цикле будет производить одно единственное сравнение.

gh0stwizard ★★★★★
()
Ответ на: комментарий от gh0stwizard

огранизовать бинарное дерево сравнений...

anonymous
()
Ответ на: комментарий от anonymous

Спасибо, в итоге взял из этого сорца fastlog2 с мультипликатором, проблема решена, осталось юниттестами проверить на широком диапазоне.

Спасибо.

westtrd
() автор топика

а что если табличку значений для каждого числа завести? :) Если по полбайта на число, то всего 2ГиБ получится

Что-то меня терзают смутные сомнения насчёт этичности оказания помощи людям, вредящим мировой экономике :)

Harald ★★★★★
()
Ответ на: комментарий от westtrd

В итоге средняя 15 тактов на вычисление десятичного логарифма, в 10 раз разница.

westtrd
() автор топика

Почему нельзя писать со сдвигом-запасом, потом по факту переносить? По бранч-миссам, как насчет попробовать cmp/cmov, или его выпилили в новых процах?

И внесите уже царя, кто-нибудь.

arturpub ★★
()
Ответ на: комментарий от Harald

Существует много точек зрения насчет вредности, ни одна не может быть признана безупречной.

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

westtrd
() автор топика
Ответ на: комментарий от arturpub

Потому что как вышло в итоге 15 тактов в среднем на вычисление с тестом 1000000 итераций и записью фейков в разные слоты памяти, я очень сомневаюсь, что это будет уместно.

В продакшне память будет cache friendly, так что проблем тут не будет, префетчер обычно настраивается.

westtrd
() автор топика
Ответ на: комментарий от gh0stwizard

Первый вариант можно на дихотомию переделать. Будет быстрей.

Массив, как предлагаешь, — не самое лучшее решение, т.к. разыменовывание — операция дорогая. Нужно использовать именно сравнение с константами.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от westtrd

Строка в совершенно определенном формате потом уходит в TCP socket.

Я конечно дико извиняюсь за оффтоповый вопрос, но если все генерируемые строки идут в гнездо, то для чего считать наносекунды в свете нехилого оверхеда самого гнезда?

Pavval ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.