Комментарии 44
Пять процентов ошибок. Звучит как отличный KPI, если подумать. Мой предсказатель веток в жизни (он же интуиция) работает сильно хуже.
а вы на одних и тех же данные сравниваете?
человек отлично видит паттерны вроде 110110110.
Предсказатель ветвлений это удивительно, но интуиция человека порой кажется просто волшебством
Джун правда сильно удивился рассказу про алгоритм ветвления?
30+ лет назад этому учили на специальности "ЭВМ, комплексы, системы и сети".
Это вроде совсем основы IT?
P.S. Публикации+ поставил. Вспомнил IT молодость 👴
Ага, а ещё раньше игры были оптимизированными. Если у джуна есть тяга к знаниям (все зависимости от их текущего объема) это уже победа я считаю, неиронично, очень ценно.
30+ лет назад...
Непонятно что вы хотите доказать, но TAGE был придуман в 2006, а первые процессоры с таким предсказателем вышли в 2010+.
То что было 30 лет назад, сейчас никуда не годится.
Это вроде совсем основы IT?
Для большинства людей, что-то более низкоуровневое чем Python, это тёмный лес.
Но 30+ лет назад джуну не надо было знать про вайбкодинг, restapi, различия ssr/csr, -подставьте-из-своего-домнена-.
Обалдеть! Напиток Бравндо содержит электролиты!1
Вы прикалываетесь, или серьезно? Чего еще не знает Ваш сферический джун? Предсказание ветвлений лет так 30+ насчитывает, начиная с Pentium-1.
Пусть еще джун немного схемотехнику материнских плат покопает, погуглит "Гитарюга power on sequence" и узнает, что основной процессор запускается последним, когда ему разрешат процессоры южного и северного мостов. И такое прочее. Статья позорная получилась.
Дайте почитать Михаила Гука этим сферическим джунам, может немного мозга в голове появится.
Хотя вайб-кодинг решит эту проблему. Нет знаний, нет проблем. Вкалывают роботы, счастлив человек. intelligence_happiness_liza_simpson.jpg
Чтобы "побороться" с Meltdown-Spectre, которые существовали только в лабораторных условиях, в винду подвезли патчи, снизившие ее производительность процентов на 30%.
Ой вей.
Не переоценивайте людей, которые делают запрос в gpt на подобии "Какой язык самый быстрый? Перепиши на него код сайта"
COBOL кстати уже насчитывает 64 года, но мало кто его знает почему-то
Схемотехнику, я уверен, вообще никто не откроет из тех кто только начинает свою карьеру
Будем честны, её и из тех, кто вовсю поддерживает работающие системы, не такой большой процент читали (или читают) и, самое главное, помнят и знают.
Я лично знаю, что процессор стартует не в первую очередь. Но конкретно когда... За несколько лет работы сервера старт у него может быть один раз, так что пока незнание проблемы не составило (а если бы и составило - сел бы, разобрался).
Хм, а вы так же реагирует на вопросы новичков/учеников/студентов? Я просто знаю несколько людей, которые делают "глубокий вздох" на любой вопрос и с ними не любит работать почти никто.
Все мы в чем-то новички; человек, который говорит, что он спец в том или ином деле - либо подлец, либо идиот.
Новички бывают 2 типов: с пытливым умом, и с отсутствующим критическим мышлением. Вторые пишут вопросы вроде "а если у сим-карты маркером закрасить один контакт, правда что интернет станет бесплатным?", и таким в IT делать нечего. Ребят с пытливым умом я уважаю. Они обычно какое-то самостоятельное исследование проводят (как то просто гуглят), и затем задают вопросы. Ребята второго типа (=сорта) хотят готовое на блюдечке и совсем не хотят думать, к сожалению. Но при этом колотят понты будь здоров.
А так да, я знаю что ничего не знаю. Всем гуглить Даннинга-Крюгера.
В "глубокий вздох" сейчас превратился бывший ранее популярным ресурс Wasm (https://wasm.in). Такое наблюдать очень печально.
С другой стороны, отсылка к фильму "Идиократия" мной сделана не просто так.
Истина где-то посередине. Хабр же начал постепенно превращаться во что-то странное.
Можно задаться целью понять, когда мы свернули не туда. Примерно в 2012. На Хабре статья с картинкой очков на фоне монитора в ленте "лучшее за все время", а Васм как раз был топчиком, исследования и обсуждения кипели, после чего началась резкая его стагнация.
Полагаю, во всем виноват интернет, его массовое проникновение.
"Я же понимаю, что в этих ваших коробочках - все знания мира. Но отбери его (смартфон) у вас, и вы двухзначное число не сможете сложить. А для созидания нужно, чтобы знания вот здесь были, в голове, чтобы синтез какой-то был. А иначе вы будете производить только углекислый газ." "Вы живете в обществе, где никто ничего не знает, но имеет мнение по любому вопросу."
(с) Гости из прошлого 1 сезон 4 серия
Не знаю, не знаю. Кто "внаглую" спросит "а если у сим-карты маркером закрасить один контакт, " , так или иначе быстро получит "нормальный" (его точки зрения ответ), быстро поймёт через 2-3 интерации, что так не выйдет(а не поймёт , таким в IT делать нечего) . А кто будет мелкими вопросами цедить, чтобы не дай бог его не покарали , дойдёт к цели гораздо дольше.
С мыслью про то, что 99% кода руками под это трогать не надо, согласен полностью. Полезно понимать механизм, полезно помнить про горячие места, но превращать каждую ветку в битовую головоломку ради потенциальной красоты в бенчмарке - так себе затея
Я подозреваю в случае отсортированного массива надо сначала найти первое 128 методом половинного деления, а потом складывать только вторую часть массива. Код со сдвигом конечно хорош, но в плане читаемости довольно хрю-хрю, использовать надо только когда сам массив большой. Нет, так-то в критически производительных участках и goto незазорно использовать, но это мягко говоря нишевые приём.
А зачем искать? Крутить от конца - префетчеру без разницы.
Помнится недавно была статься на тему, что глюк когда имя ендпойнта заканчивается на m. И как раз там был типа такого кода проверки. В патче заменили на обычный if
Ссылка на упомянутую статью
Неотсортированный массив: значения прыгают хаотично. 73, 201, 14, 255, 99, 182... Предсказатель видит: да, нет, нет, да, нет, да... Никакого паттерна. Он ошибается в ~50% случаев. Каждая ошибка — flush конвейера. Код ползёт.
Я всё-таки за дотошность, аккуратность и стогость формулировок. У предсказателя переходов есть на самом деле несколько уровней. На самом нижнем он действительно смотрит на паттерн повторения и параллелит бранч, если он будет "взят". Но там также есть и ещё второй уровень памяти, так что когда значения прыгают хаотично, он всё равно обучается и "ошибается на 50%" лишь в первый раз. И когда вы второй раз пойдёте по тем же самым значениям, он это вспомнит (а у вас тем внешний for цикл есть). Размер этого "кэша" истории не документирован, в отличие от кэшей данных и инструкций, но на Хасвелле он составляет примерно 4К,я проверял Обычно таки в подобных тестах спускаются на уровень ассемблера и попутно считают количество инструкций на такт, и всё встаёт на свои места и раскладывается по полочкам. Эх, где-то была статья, да вот найти не могу. Попробуйте поиграть размером массива от килобайта до нескольких - вы будете приятно удивлены.
Одна смотрит на последние 4 перехода, другая — на 8, третья — на 16, четвёртая — на 64... Геометрическая прогрессия.
Это не геометрическая прогрессия.
Торт)
Но если вы пишете горячий цикл, который обрабатывает миллионы элементов, вот тогда стоит задуматься:
интересно, какой процент читателей, действительно, хоть раз в жизни, написали или хотя бы пытались сделать горячий цикл действительно горячим.
99.8% точность. Но для реального кода этого мало.
Точность уже 85–90%. Неплохо.
Результат? 95–97% точность на реальном коде. На некоторых бенчмарках — 98%
Где логика?
Джун смотрел на меня как на сумасшедшего
В этом и заключается глобальная проблема, что программирование как профессия становится кодерством. Ну, как у Стругацких с их "девочками" из Понедельника. Как можно идти в любое программирование, даже самого завалящего фронтенда для казинычей, не понимая, как работает твой рабочий инструмент? Не прочитав хотя бы Паттерсона?
Доабстрагировались, блин.
Когда вы едете на велосипеде, вы знаете марки стали в цепи? А на автобусе знаете, сколько пробег у шин? Очевидно, нет, но не менее очевидно, что оно вам и не надо. Где-то есть граница "обязательно (статья 105 УКРФ) / полезно (статья 127 ТКРФ) / совсем неважно (03.08.1995 N 123-ФЗ)".
Я, как бэкендер, на деле буквально один или два раза за всё время сталкивался с необходимостью `EXPLAIN`, не говоря про реализацию СУБД, а тем более про уровень железа.
Джуну не рановато ли думать про производительность?
На Java получилось в ~1.45 раза (86.6 сек vs. 59.6, Intel Ultra 7 255U):
public class t{
public static int[] aiAr = new int[1000000];
public static Random oRnd = new Random();
//-- -------------------------------
public static void main(String[] argv){
int i, j, iSum, iArSize;
long lBegTS_ns, lEndTS_ns, lDiff_ms;
// CODE
//-- ---------------
iArSize = aiAr.length;
for(i = 0; i < iArSize; i++){
//aiAr[i] = oRnd.nextInt(256); //-- not sorted;
aiAr[i] = i; //(i % 256); //-- sorted;
}
//-- ---------------
//-- warm-up JIT ---
iSum = 0;
for(i = 0; i < 100; i++){
for (j = 0; j < iArSize; j++){
if(aiAr[j] >= 128){iSum += aiAr[j];}
}}
//-- ---------------
//-- ---------------
lBegTS_ns = System.nanoTime();
for(i = 0; i < 10000; i++){
for (j = 0; j < iArSize; j++){
if(aiAr[j] >= 128){
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
iSum += aiAr[j];
}}}
lEndTS_ns = System.nanoTime();
lDiff_ms = (lEndTS_ns - lBegTS_ns)/1000000L;
//-- ---------------
System.out.println("Diff .....: [" + lDiff_ms + " ms]");
return;
}//End of <static void main(String[] argv)>
//-- -------------------------------
}//End of <class t>По ходу чтения статьи кое-что гуглил, и наткнулся на замечательный тред, которому более 17 лет:
https://www.reddit.com/r/programming/comments/8fqgy/cmov_instruction_a_bad_idea_on_outoforder_cpus/
Люди из другого времени обсуждают оптимизации под Пентиумы. Кто-то в комментариях даже предложил использовать два бита под предсказания - несколько я знаю, позднее так действительно стали делать на практике.
Кстати, для того, чтобы избегать ветвления, вовсе не обязательно избегать операторов сравнения. Надо просто не размещать их в конструкциях ветвления.
На мой взгляд, вот такой код - это же колдунство какое то:
int t = (data[j] - 128) >> 31; // 0 если >= 128, -1 если < 128
sum += ~t & data[j];
тот же эффект будет, если написать:
sum += static_cast< int >(data[j] >= 128) * data[j];
или вообще просто и понятно:
sum += (data[j] >= 128) ? data[j] : 0;
тут даже беглого взгляда достаточно для того чтобы понять, что делает код.
это же колдунство какое то
для тех, кто не знает, как представляются числа в дополнительном коде.
В любом случае оригинальный if(data[j] >= 128компилятор сворачивает в cmov и ничего делать не нужно.
для тех, кто не знает, как представляются числа в дополнительном коде.
да нет, для всех колдунство. Вместо простого прочтения кода дальше, особенно если первый раз его видишь, тут надо напрячься и сообразить что же этим хотели сказать. В прицнипе, если оставить хороший комментарий, то это может нивелировать этот недостаток :)
Так ведь тернарный оператора — это тоже ветвление, и во что компилятор его переделает — одному компилятору известно. Битовый сдвиг в ветвление не переделается никогда.
Ну и про колдунство — это вы сильно.
Совсем недавно наткнулся на забавную штуку.
Если очень грубо, есть три функции:
— A вызывает C;
— B вызывает C, после этого в функции B есть цикл, в котором проверяется результат выдачи C, это много тысяч проверок.
Каждая из функций A и B вызывается несколько тысяч раз: сначала только A, затем только B.
— Функция С при вызове из функции А работает 6 секунд.
— Функция С при вызове из функции В работает 8 секунд.
Входные данные абсолютно они и те же. Замеры через профилировщик делались, не на глаз.
Как только в цикле проверки в функции B поменял условие на противоположное (и переставил местами блоки в if/else), время работы функции C стало одинаковым при вызове из разных мест.
Причины понятны, но сам факт того, что эффективность работы функции может зависеть от того, какой код работал до неё, доставляет. Теория алгоритмов рыдает где-то в углу.
Вообще страшно такое читать. Функция работала 8 секунд и этого времени не хватало, чтобы предсказатель адаптировался, выкинув более ранние предсказания.
Или имелось в виду, что не сама фукнция С работала 8 секунд, а в функции В она вызывалась многократно и суммарное время всех этих вызовов было 8 секунд? Тогда причины понятны, да.
Тут уместно будет вспомнить первые 2 правила из 5 правил Роба Пайка:
Не угадывайте узкие места: Вы не знаете, где код работает медленно. Чаще всего они находятся там, где их не ждут, поэтому не оптимизируйте заранее.
Измеряйте (профилируйте): Не пытайтесь оптимизировать, пока не провели измерения и не убедились, что код реально тормозит.
Очень интересный кейс. Ветвление, по идее, не должно влиять на перформанс настолько сильно благодаря спекулятивному исполнению. Решил повторить бенчмарку и, к сожалению, воспроизвести результат не получилось:

Может ли быть так, что на перформанс в статье больше влияет обращение к памяти или не очень удачная векторизация?
Кажется, наш главный bottle neck - это один единственный аккумулятор. И у ядра должно быть достаточно ресурсов, чтобы параллельно посчитать и if (true), и if (false), а затем засунуть в аккумулятор правильное значение после того, как узнает правильный ответ.
11.2 секунды против 1.9 секунды
В это время включена сортировка?
ошибается в 5% случаев
Т.е. процеср выполняет 95% предсказуемой монотонной работы. Мозг вот экономит энэргию на этом, а если ево предсказание поступающей информацыи превышает эти условные 95%, то вообще начинает уходить в сон средь бела дня.

Процессор в вашем компьютере угадывает будущее. И ошибается в 5% случаев