LINUX.ORG.RU

Объясните сишную магию v2

 ,


2

4

В продолжение темы: Объясните сишную магию

Ковыряю сорцы Skia и наткнулся на такой забавный ужас (ссылка):

int fLastMoveToIndex = 5; // любое число
fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1);

Экспериментально удалось выяснить, что данный код меняет знак и отнимает 1 только если число положительное. Как он это делает - я даже знать не хочу.

Вопрос: что мешало написать банальный if, или хотя бы оставить комментарий? Типичное сишное какерство?

PS: производительно данного куска кода на погоду не влияет.

★★★★★

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

Ядро линукса на 20 млн строк компилируется где-то два часа процессорного времени

У вас первопень? Ядро линя собирается пару минут на современном железе

Intel i7 5820 собирает ядро 4.17 за 20 минут реального времени, то есть 2 часа процессорного времени (на одно ядро):

https://www.reddit.com/r/Amd/comments/8lffvs/lets_compile_a_linux_kernel_and_...

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

на одно ядро

21-й век на дворе. Какой смысл считать на одно ядро? Или fpc не умеет в параллельную сборку?

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

21-й век на дворе. Какой смысл считать на одно ядро? Или fpc не умеет в параллельную сборку?

Как-то ты неуклюже пытаешься слиться с «2 минут».

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

Хочешь извращений - пиши тесты и документацию.

согласен.

По поводу магии: https://en.wikipedia.org/wiki/SEX_(computing)

в Motorola 6809. была инструкция sex(Sign EXtend):

  1. Принимала на вход знаковое целое

  2. Если число положительное или 0 возвращала 0

  3. Если отрицательное, то возвращала число в котором все биты равны 1.

также

n ^ 0 == n

n ^ 0xFFFFFFFF == ~n

тогда приведённая строка

fLastMoveToIndex ^= ~sex(fLastMoveToIndex);

читается не сложнее чем

if (fLastMoveToIndex >= 0) {
    fLastMoveToIndex = ~fLastMoveToIndex;
}

и не воспринимается как какая-то магия…

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: комментарий от bigbit

Вон в POWER тоже есть stwu (store word and update), так что, теперь POWER RISC’ом не называть?

Там таких сложных операций можно по пальцам пересчитать. МОжно называть это «легкий налет CISC».

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

В 2020 году стало актуальным понятие «эффективность» вместо «производительность». То есть, насколько много может посчитать твой процессор на ватт потребляемой энергии. И CISC системы здесь встречают значительные проблемы из-за того, что нужно иметь большое число параллельных вычислителей, результат работы большинства из которых отправляется вникуда.

К слову, потому в видеокартах процессоры являются RISC и VLIW: http://developer.download.nvidia.com/compute/cuda/3_1/toolkit/docs/ptx_isa_2....

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

21-й век на дворе. Какой смысл считать на одно ядро? Или fpc не умеет в параллельную сборку?

Параллельная сборка независимых модулей делается, например, Jedi. Update: однако, она имеет мало смысла без параллельной линковки, поскольку время компиляции сравнимо со временем линковки.

Какой смысл будет иметь цифра «я собрал проектнейм за 3 минуты»? Какой вывод я из этого смогу сделать? Ты собирал на одноядерном ноуте или на 96-ядерном 192-поточном сервере? Зато процессорное время ясно и понятно, особенно если учесть, что производительность на ядро почти не растет уже лет десять.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от fsb4000

в Motorola 6809. была инструкция sex(Sign EXtend):
Принимала на вход знаковое целое
Если число положительное или 0 возвращала 0
Если отрицательное, то возвращала число в котором все биты равны 1

CDQ на x86 делает то же самое, и является одним из вариантов оптимизированного кода для исходной обсуждаемой программы.

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

Как-то ты неуклюже пытаешься слиться с «2 минут»

Ну может у него 48 ядер, кто ж его знает — цифра вполне правдоподобная.

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

Он сравнивает несравнимое: «ядро линукс» и «неизвестную наколеночную утилиту намного меньшего размера».

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

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

Зато процессорное время ясно и понятно, особенно если учесть, что производительность на ядро почти не растет уже лет десять.

Сестра! Сестра!

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

особенно если учесть, что производительность на ядро почти не растет уже лет десять.

да тут галоперидол нужен. Интел каждый год продолжает делать процессоры всё быстрее, не меняя частоту.

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

Помню ты в прошлый раз писал что плюсисты поехавшие и «так писать нельзя», а оказалось что код написан так с определенной целью, и более того, работает быстрее.

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

Врача вызывали?

https://www.cpubenchmark.net/cpu.php?cpu=Intel Core i5-680 @ 3.60GHz&id=771

https://www.cpubenchmark.net/cpu.php?cpu=AMD Ryzen 3 3100&id=3715

Смотреть на «Single Thread Rating». Рост в полтора раза за 10 лет.

Update: да, я уверен, что сейчас придут возмущающиеся тем, что я не те классы сравниваю. Хорошо:
https://www.cpubenchmark.net/cpu.php?cpu=Intel Core i5-10600 @ 3.30GHz&id... — 2900 сусликов в 2020 против 1600 сусликов в 2010. По прежнему не в два раза.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 2)
Ответ на: комментарий от byko3y

Ну давай, назови мне проект, для которого критично 10-20 % скорости работы?

Да куча их хром (включая в8, скию), aco, хотспот, линукс.

И сколько оно даст? Хотя бы в половину сократит время?

Конечно, почитать можешь сам.

paramon
()
Последнее исправление: paramon (всего исправлений: 1)
Ответ на: комментарий от byko3y

Проблема в том, что вы сравниваете тёплое с мягким. Вы не учитываете частоты, доступные инструкции (SIMD) и даже банальный тротлинг и турбо буст. Я молчу про io и вмешательство ОС (привет виндовый антивирус).

RazrFalcon ★★★★★
() автор топика

RazrFalcon, как имеющий отношение к графике, можешь хоть как-то объяснить смысл этой переменной. Мои допущения. «f» в начале переменной означает, что в начале это был флаг, то есть должен быть «bool». Но почему-то это переменная целого типа. Побитное отрицание «~» - это во что превратилось булево отрицание из-за рефакторинга «bool -> int». А вот остальная магия непонятна. Это попытка совместить флаг и целочисленную переменную неизвестного назначения?

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

И сколько оно даст? Хотя бы в половину сократит время?

Конечно, почитать можешь сам

Я читал уже, но это не я ссылаюсь на значимость этих механизмов:

https://habr.com/ru/post/503302/
«Как можно увидеть, в моем случае в результате предварительной компиляции заголовков, время сборки в итоге уменьшилось с 43 до 35 минут».

Я почему и спросил: пополам время компиляции сократит? Потому что я знаю, что не сократит.

Да куча их хром (включая в8, скию), aco, хотспот, линукс

Бенчи моего проекта на Vue.js. Открытие страницы:

33 ms Loading
220 ms Scripting
175 ms Rendering
42 ms Painting
222 ms System
8175 ms Idle
8866 ms Total

Тыкание в кнопки и переключение окошек:

81 ms Loading
4163 ms Scripting
2040 ms Rendering
379 ms Painting
1331 ms System
14569 ms Idle
22563 ms Total

Открытие окна предпросмотра печати:

3190 ms Painting
19373 ms Idle
22563 ms Total

Загрузить эту страницу треда и открыть форму создания сообщения:

33 ms Loading
220 ms Scripting
175 ms Rendering
42 ms Painting
222 ms System
8175 ms Idle
8866 ms Total

Здесь Rendering — это вычисление стилей, макета страницы, обработка хитбоксов, а Painting — это само рисование.

По поводу скриптов я могу сказать, что скрипты оптимизируются примерно до тех пор, пока пользователя не перестанет тошнить от сайта. И то меня лично от ютьюба воротит на Firefox-е. И нет, в хроме эту проблему решали не через супербыстрые V8 и Skia, а через новые костыльные интефрейсы в браузере, которые позволяли быстро грузить видео и потихоньку догружать остальную страницу — нынче уже и в Firefox добавили поддержку этого «чего-то» (shadow DOM, что ли).

хотспот

Как правило, в 2020 году жава использется на каких-то более-менее ответственных серверах и сервисах, которые работают во много потоков и проблема производительности которых часто решается докидыванием железа. Да, приятно иметь чуть больше производительности при тех же затратах, но вообще-то пофик на эти 20%.

линукс

Очень широко берешь. Если брать ввод-вывод, многопоточку на спинлоках, и частые переключения контекстов, то там влияние оптимизаций компилятора составляет плюс-минус ноль, а основную роль играют сами алгоритмы. А что у нас там ресурсоемкого в ядре живет-то?

aco

Не знаю такого.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Вы не учитываете частоты

Они не имеют никакого значения и не связаны с производительностью.

доступные инструкции (SIMD)

https://www.sigarch.org/simd-instructions-considered-harmful/ — так что спорно.

и даже банальный тротлинг и турбо буст

Как раз на одном потоке тротлинг не оказывает никакого влияния на максимальную производительность ядра. Самый-самый-самый топовый проц почти дотянул до двухкратного роста:
https://www.cpubenchmark.net/cpu.php?cpu=Intel Core i9-10900 @ 2.80GHz&id... — но это уже i9, а проц 2010 года был i5.

Я молчу про io и вмешательство ОС (привет виндовый антивирус)

Бенч берет данные с большого числа самых разных систем. В том числе нужно понимать, что процессор 2020 года скорее всего работает на намного более быстрой памяти, чем процессор 2010 года. Что там было? DDR3-1333? А сейчас уже DDR4-2666.

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

обрати внимание, что msvc эту оптимизацию не делает, а делает честное ветвление

Из этого, а также того факта, что clang есть на эту вашу, следует что msvc не нужен :D

Есть только на одну ОС, оптимизирует хуже, чем аналог, да ещё и исходники закрыты :P

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

Из этого, а также того факта, что clang есть на эту вашу, следует что msvc не нужен
Есть только на одну ОС, оптимизирует хуже, чем аналог, да ещё и исходники закрыты

И чем ты собрался на винде компилить? GCC? Даже если ты будешь шлангом компилить, тебе все равно будут нужен Windows Kit, а он писан под MSVC. А иначе прокладки и эмуляции.

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

Я читал уже, но это не я ссылаюсь на значимость этих механизмов:

Zapcc почекай.

Бенчи моего проекта на Vue.js

Но хром постоянно пытаются оптимизировать.

Очень широко берешь.

Но мы оба понимаем о чем я.

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

В некотором роде ты прав.

Только, f - field, соглашение в коде skia.

Магия в том, что (вроде) пытаются совместить в одной переменной признак замкнутости контура поли-линии и количество узлов задействованных для этого. Или что-то похожее, я не понял с первого взляда. Короче, вся непонятность из-за придания дополнительной семантики уже задействованной переменной. Экономия на спичках и хацкерство, имхо.

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

f действительно означает flags, но это не значит что переменная должна быть bool. Вполне ожидаемо увидеть здесь целочисленное. Просто подсказка что в данной переменной хранятся битовые флаги.

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

Это аналог:

uint last_move_to_index;
bool move_to_required;

То есть они хранят флаг и индекс в одной переменной. Смысла от этих приседаний 0, ибо не hot path.

RazrFalcon ★★★★★
() автор топика

This

Вот поэтому писать надо на нормальных языках. И он один, это ADA. Там такой херни нет.

anonymous
()
Ответ на: This от anonymous

Вот поэтому писать надо на нормальных языках. И он один, это ADA. Там такой херни нет.

Очередной дно эксперт?

Конечно есть:

https://www.adaic.org/resources/add_content/standards/05aarm/html/AA-B-2.html

Shift_Right_Arithmetic

Как и в Pascal, Rust и многих других

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

В некотором роде ты прав.

Только, f - field, соглашение в коде skia.

Это слишком уж слишком толерантно. :) Говори как есть - не прав. Это же интернет.

Короче, вся непонятность из-за придания дополнительной семантики уже задействованной переменной

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

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

PS: производительно данного куска кода на погоду не влияет.

Точно, во всех программах, использующих Skia?

Данный кусок кода не находится в hot path.

Это же библиотека. Её код окажется в hot path множества других программ. (Ну или из-за гугл-политики релизов их «собственного» свободного ПО - не множества). По крайней мере этот код из SkPath::close(). SkPath может состоять и из небольшого кол-ва элементов.

Но комментарий в коде «компиляторы до сих пор надёжно не оптимизируют эту идиому на if/else» не помешал бы. А ещё лучше, наверное, было бы вместо этого куска #if 0 / #else / #endif сделать инлайн-функцию с говорящим названием.

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

Видимо у нас разное представление о hot path. Данный код не влияет на производительность от слова совсем.

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

Смысла от этих приседаний 0, ибо не hot path.

Даже если hot path, работа/арифметика с индексом становиться нетривиальной – распаковка-изменение-упаковка индекса.

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

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

А можно поподробнее?

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

И?

Значит на Ada тоже можно записать этот код через xor и Shift_Right_Arithmetic, вместо if и not.

Тогда вопрос:

Там такой херни нет.

какой там херни нет, если код переписывается 1 в 1?

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от fsb4000

Ada не предоставляет логических (битовых) операций над целочисленными типами, она предоставляет их для модульных типов

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

Я читал уже, но это не я ссылаюсь на значимость этих механизмов:

Zapcc почекай

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

Но хром постоянно пытаются оптимизировать.

Что значит «пытаются»? Я вот сейчас запустил хром 4-летней давности — не замечаю никакой разницы. Может быть там и есть 20%, но для пользователя это значит «ничего», поскольку пользователь не сможет отличить 1.1 секунды времени реакции от 1.3 секунды.

То что они добавляют хардкод под свои сервисы, ака «новые фичи» в браузер — это да, есть такое. Shadow DOM — самый крупный, известный, универсальный из них, и при этом решительно бесполезный, поскольку не дает значимых преимуществ над React/Vue/Angular, и в реальности служит лишь для «Firefox тормозит больше в сервисах гугла», что сошло на нет с реализацией поддержки Shadow DOM в Firefox — но никакого решительного повышения производительности Shadow DOM не дал, гугл подумывает сделать новую платформу с нативным интерфейсом, ровно как и Facebook делает React Native чтобы хотя бы прийти к производительности жабы на андроиде, а не браузера с JS.

Очень широко берешь.

Но мы оба понимаем о чем я

Не понимаем. А я задал вполне конкретный вопрос:

А что у нас там ресурсоемкого в ядре живет-то?

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

miltorg

miltorg скорее «широкий пользователь» /150 кг это огого!/.

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

Там даже microcode есть. А где он есть - то это уже не RISC.

За статью спасибо. Конечно, когда у тебя процессор расчленяет исходные инструкции на мелкие, и уже мелкие выполняет — это никакой не RISC, тут ты расставил точки. С другой стороны, микрокод прост, и люди так и норовят назвать это недомикрокодом — здесь я добиваю аргументом о том, что CISС код ARM просто-напросто оптимизирован под микрокод и суперскалярный исполнитель, что позволило применить более компактный микрокод, чем на x86.

В упомянутом выше PowerPC тоже есть микрокод, но на считанные инструкции, и их советуют избегать, для чего в том же GCC есть специальные флаги:
https://cellperformance.beyond3d.com/articles/2006/04/avoiding-microcoded-ins...

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

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

А можно поподробнее?

Паскалевый компилятор попадает в ту же проблему, что и компилятор Си: кольцевые зависимости модулей заставляют компилятор парсить модули заново, что при очень большом числе модулей дает замедление более чем на порядок. Проблема решается сокращением взаимных зависимостей, что частенько ограничивается банальным устранением пустых подключений модулей — когда модуль упомянут в uses, но реально ничего из интерфейса подключаемого модуля не используется, а парсить интерфейс подключаемого модуля приходится снова и снова, чтобы понять, что нам из этого интерфейса ничего не нужно.

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

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

За такие комментарии надо по лицу рукой сжатой в кулак давать.

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