Здравствуйте, netch80, Вы писали:
N>Подходящего ARM под рукой нет. Если есть — проверьте там
Нет, у меня под рукой только мой рабочий лэптоп. Впишу всё же:
i7 8750H: ~8% добавки.
N>Ну что тут сказать... почему-то у Intel очень долго была такая специфика: они всегда хуже делали арифметику, а деление у них вообще в загоне. Правильные методы работы с денормализованными (которые не тратят до 200 тактов на операцию) AMD начал внедрять на несколько лет раньше — пока Intel отделывался флажками типа "плевать на них, все меняем на ноль". Деление плавучих по Голдсмиту — тоже раньше (пока Intel сохранял SRT, знаменитый по FDIV bug). Может, для своих целей оно им и правильно... Но то, что на 10-м поколении Core разница ушла — показывает, что и они умеют учиться.
Плавучка вообще мало интересует, там, где таки да, воркэраунд с выключением денормализации устраивает.
В конкретно этой задаче, где делитель известен в рантайме, но при этом часто не меняется, присматривался к https://libdivide.com/
Здравствуйте, Vamp, Вы писали:
V>Данный код предполагает, что расстояние между началом и концом уменьшается в 32 бита, и в рамках этого предположения работает отлично. Если заменить тип управляющей переменной на unsigned int, скорость кода заметно уменьшится. Связано это с тем, что компилятору придется контролировать переполнение на каждой операции (как правило, путем засовывания числа в отдельный короткий регистр), так как беззнаковые целые разрешают переполнение. Классическая рекомендация — использовать знаковое целое.
А как это контролируется, можно чуточку подробнее? Что за короткий регистр?
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Ну скорее всего это не криминал. 2 миллиарда элементов в контейнере — это, воля ваша, что-то не то. Если иметь в виду, что гранулярность выделения по malloc, ЕМНИП, 16 байт, то это 32 Гигабайта. Едва ли в большинстве задач такое возможно. Да и скорее всего тут будет что-то более сложное, чем простой контейнер.
Для какой-нибудь бигдаты это копейки, у фб скоро пользователей будет больше. В скором времени, если не сейчас, это уже обычное явление.
Здравствуйте, Sharov, Вы писали:
PD>>Ну скорее всего это не криминал. 2 миллиарда элементов в контейнере — это, воля ваша, что-то не то. Если иметь в виду, что гранулярность выделения по malloc, ЕМНИП, 16 байт, то это 32 Гигабайта. Едва ли в большинстве задач такое возможно. Да и скорее всего тут будет что-то более сложное, чем простой контейнер.
S>Для какой-нибудь бигдаты это копейки, у фб скоро пользователей будет больше. В скором времени, если не сейчас, это уже обычное явление.
На 64-битке и так обычно индексы в размер указателя (хотя, думаю, мест, где осталось int, до чёрта).
Вот Java жалко — там у контейнеров типично int size(), а не long size().
Здравствуйте, netch80, Вы писали:
N>Тики по GetTickCount специально рассчитаны на такой режим. Но у тебя это работает потому, что в C/C++ unsigned уже гарантированно сделано арифметикой по модулю. N>В Ada это отдельный тип чисел: "type counter32 = modulo 2**32" и т.п. (модуль не обязан быть степенью двойки). Вот там, да, штатно такая арифметика (без защиты на заворот).
Что подразумевается под защитой на заворот -- исключения или какая-то манифестация при переполнении?
Здравствуйте, netch80, Вы писали:
N>Но это паршивенькие реализации. Проблема в том, что в них, как и в x86, обработка исключений не вышла из каменного века и требует обязательного перехода в режим супервизора. N>Из более-менее заметных архитектур только в RISC-V озаботились вопросом "как исключения, которые не нужно гонять на высокие уровни, обрабатывать без переключения", но это только последние лет 5 и пока нету доступных реализаций в железе. Но RISC-V принципиально не генерирует исключения на целочисленную арифметику, даже на деление на 0.
Здравствуйте, Философ, Вы писали:
Ф>Особенно, когда отрицательным значением задаются размеры в структурах: мы ведь не можем быть уверены, что переданный буфер не имеет отрицательного размера.
Размеры структур я уже давно считаю типом size_t, для того он и задуман был. Кстати, в QT размером STL-like контейнеров (QVector, QMap, QSet, etc), который возвращает функция size(), оно же typedef size_type внутри контейнеров, является тип int, внезапно.
Здравствуйте, Sharov, Вы писали:
N>>Но это паршивенькие реализации. Проблема в том, что в них, как и в x86, обработка исключений не вышла из каменного века и требует обязательного перехода в режим супервизора. N>>Из более-менее заметных архитектур только в RISC-V озаботились вопросом "как исключения, которые не нужно гонять на высокие уровни, обрабатывать без переключения", но это только последние лет 5 и пока нету доступных реализаций в железе. Но RISC-V принципиально не генерирует исключения на целочисленную арифметику, даже на деление на 0.
S>В смысле? И что вернется при делении на 0?
Частное — значение из всех единичных битов. Остаток = делимому.
P.S. FYI: на AA64 по доке в этом случае частное = 0, тоже безо всяких исключений.
Здравствуйте, Sharov, Вы писали:
N>>Тики по GetTickCount специально рассчитаны на такой режим. Но у тебя это работает потому, что в C/C++ unsigned уже гарантированно сделано арифметикой по модулю. N>>В Ada это отдельный тип чисел: "type counter32 = modulo 2**32" и т.п. (модуль не обязан быть степенью двойки). Вот там, да, штатно такая арифметика (без защиты на заворот).
S>Что подразумевается под защитой на заворот -- исключения или какая-то манифестация при переполнении?
Генерация исключения.
Повторить в 5 минут:
Берём код, кладём в aplusb.adb.
Запустить gnatmake aplusb.adb.
Запускаем программу, пишем ввод и получаем:
Да, есть. Это уже неплохой шаг по продвижению к полноценной реализации, хотя очень частичный.
И очень правильно, что они сделали это синтаксическим контекстом.
Но для полной версии это требует расширения, например, в 3 этапа:
1) Как GCC overflow builtins, но с добавлением сдвига влево;
2) Функции классов чисел на конкретные операции в конкретном режиме (одном из: truncated, checked with flag, checked with exception, relaxed; если есть настроение, ещё и saturated);
3) Контекст для автоматического задания режима для операторов типа + — * /
всё это реально очень несложно по сравнению с полным компилятором, но громоздко.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Даже в классической книге Кернигана/Ритчи множество примеров, где счетчики, индексы и прочие имеют знаковый тип.
Обе мейнстримовых модели целых, знаковые и беззнаковые, плохо подходят для счётчиков/индексов.
Тут должен быть тип с семантикой как у указателей — отдельный тип для значения, отдельный тип для разницы.
(собсно, указатели — это и есть индекс в участке памяти)
Значение индекса будет беззнаковым, разница знаковая.
Значения индексов можно сравнивать/вычитать, нельзя складывать.
К индексам можно прибавлять смещение и т.д. — всё как у указателей.
Соответственно, при итерировании от индекса до индекса будет логика как при итерировании по указателям.
При итерировании от одного указателя в какую-либо сторону на нужное смещение — цикл оперирует знаковым смещением до тех пор, пока смещение не будет равно 0-лю (или другому смещению).
С подобной проблематикой сталкивался при нумерации сообщений в сетевом протоколе.
Номера сообщений по стандарту беззнаковые, но разница их знаковая.
В итоге, или необходимо во внутренней логике обкладываться if-ами, или использовать числа удвоенной ширины в памяти/алгоритмах, или нарисовать свои обертки над целыми с соотв. операциями — самый правильный вариант, ИМХО.
Здравствуйте, T4r4sB, Вы писали:
TB>>>Ты на беззнаках даже тупо от ЭН до нуля проитерироваться не можешь без дополнительного бубна.
R>>А в чем проблема?
TB>i--, заменяющее сразу два блока из заголовка for? Мы вам перезвоним, ога.
Здравствуйте, Marty, Вы писали:
M>У того, кому такая запись непривычна?
Если какая-то концепция на пустом месте требует писать код непривычным способом, при этом привычный способ компилируется но порождает ошибки — то эта концепция говно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
M>>У того, кому такая запись непривычна?
TB>Если какая-то концепция на пустом месте требует писать код непривычным способом, при этом привычный способ компилируется но порождает ошибки — то эта концепция говно.
Здравствуйте, Marty, Вы писали:
TB>>Если какая-то концепция на пустом месте требует писать код непривычным способом, при этом привычный способ компилируется но порождает ошибки — то эта концепция говно.
M>Или ты просто раб привычки
Код командного проекта — не место для демонстрации скилухи.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>>>Если какая-то концепция на пустом месте требует писать код непривычным способом, при этом привычный способ компилируется но порождает ошибки — то эта концепция говно.
M>>Или ты просто раб привычки
TB>Код командного проекта — не место для демонстрации скилухи.
Здравствуйте, Mystic Artifact, Вы писали:
SVZ>>>Забыл добавить "...в нашей команде...".
TB>>В какой нормальной команде допустимы такие заголовки for?
MA> https://github.com/llvm-mirror/llvm/blob/master/lib/CodeGen/VirtRegMap.cpp#L435
MA> Смотрим код, и понимаем, что это просто нытье по поводу стиля, которое, в масштабе — ровным счетом ни на что не влияет. Если это ситуационно нужно — пожалуйста.