Помимо рассмотренных вами приложений, работающих с небольшими наборами данных, есть приложения, где узкое место — память, и активный датасет занимает несколько мегабайт.
Смысл в том, что реальность она сложнее. В ней нет такого понятия как «узкое место — память» — у памяти есть совершенно разные места, которые могут быть узкими.
Как мы уже выяснили — есть две основные метрики — летенси и трупут. Причём они не определяются примитивными определениями уровня «последовательное — трупут, а рандомное — летенси», как многие делают. Это фундаментальное-противоположные вещи, с совершенно разными свойствами.
Всё это можно определить через уровень параллельности конкретной задачи. И в зависимости от этого уровня — всё может очень сильно меняться. Допустим, как я уже говорил, вычисления — это, в основном, хорошо распараллеливаемые задачи( не нужно ограничивать параллельность потоками ОС). Это задачи упирающиеся в трупут — нет смысла приводить какие-то цифры, которые никакого отношения к данному кейсу не имеют.
Кейсы с хорошим уровнем параллелизма могут быть и memory-bound, и какими угодно. Это не значит, что они упираются в вычисления.
В таких приложениях, дополнительно наращивая объёмы данных, которые надо хранить в кеше, вы вытесняете что-то полезное из l1/l2/l3.
В кеше хранятся активные данные. Если данные неактивные — они ненужны. Это ничего не изменит. Если мы не хотим вытеснять данные из кеша — мы вообще НИЧЕГО не должны читать из памяти(кроме активного датасета). Любое чтение — вытесняет нужны данные.
Естественно, что никто и никогда не использует весь кеш, именно поэтом в нём останется это один уровень, который будет забиваться временными данными. И это абсолютно ни на что не повлияет.
И опять же, всё неправильно — активный датасет в несколько мегабайт вообще никак не зависит от llc, от l2 — влезет в l3 — зависит от l3.
В данном случае меньшие кеши имеют только одно применение — кешировать некие часто используемые данные и тут будет такое же вытеснение одного way.
Какое влияние кеши меньшие кеши могут оказывать только тогда, когда наша задача состоит из подзадач, в рамках которой много раз перечитываются данные в рамках малого датасета. Такого очень мало.
Реально подобный случай — это банальная оптимизация скалярной лапши. Смысл очень просто. Когда мы попадаем в тот же l2 — данные( а именно кешлайн) мигрируют в l1d, а т.к. скалярный лапша читает данные по 1/2/4/8 байт, то в рамках последовательного чтения — мы перечитываем этот кешлайн множество раз, до 64. Если бы он не мигровал в l1d, то мы бы множество раз читали куски из l2, что явно хуже
С учётом некой параллельности( в простонародье prefetch) — нам желательно читать сразу несколько кешлайнов. На самом деле тут и l1d не нужен — хватит буферов, но мы не об этом.
И казалось бы — мы нашли подходящий кейс, но нет — ему не нужен весь l1d — ему хватит десяток кешлайнов. Остальной кеш ненужен и ни на что не влияет.
Всё это к чему? А к тому, что очень сложной придумать кейс, в котором 1way будет не временным. Всё то, что кажется подходящим — лишь кажется.
На самом деле всё как раз наоборот — основная проблема таблицы не в том, что она захламляет кеш — нет. Это почти всегда не так. Проблема её именно в том, что её может не быть в кеше, а значит — мы словим деградацию. Но на это можно так же забить. Если у нас таблица настолько ненужная, что её нет в кеше, то её производительность вообще никак не влияет на программу.
И вот у нас есть выбор. Даже если случится так, что мы проиграем в паре вызовов диву, но — это будут те случаи, которые никак не влияют на производительность нашей программы. А вот в случае частого использования — она будет в кеше, не будет его тратить( за очень-очень редкими исключениями), но при этом будет давать профит. А раз она используется часто, то и влияние на производительность нашей программы оказывает весомое.
В конечном итоге, к чему это? Всё очень просто — таблица( если она имеет реальный профит, а это имеет, да и ещё какой( до пары порядков профита)) — лучшее решение.
Отвечать что-то бессмысленно(данному персонажу — он неадекватен в порывах своего невежества. Он будет врать, игнорировать, врать, но никогда свои промашки не признавать), но — отвечаю для тех, кому действительно интересно.
Кеши устроены в виде хеш таблицы, где корзинка выбирается как (memory address) / (line size) % (number of sets), а в корзинке хранится обычно 4 элемента.
Тут мы видим попытку натянуть свои слабые представления на реальность. Я бы мог тут придраться к «memory address» в контексте всех тех проблем, которые вызывают тот факт, что адресов два и как это решается и почему там не memory address. Я бы мог придраться к «смотрю в книгу — вижу фигу», ведь человек выше кидался в меня таблицей по кешам, где чёрным по белом написано 8-way, но у него 4. Всё это неважно.
Соответственно чтобы протерять 1Kb кеша достаточно пройтись по данным с шагом 64 байта. Это затронет максимум корзинок.
32kb кэша — это 512 кешлайнов, при 8-way — это 64бакета.
Таким образом проход под массиву из 2к в среднем попадёт в 32бакета, что вытеснит 2кб. Мало того, что вы не умеете делить 25+ на 5, вы ещё и не смогли правильно посчитать ширину таблицы.
Но, в чём смысл — в любом кейсе, кроме одного(когда мы работаем на датасете шириною в кеш) — 1way никогда не используется, т.е. он временный и вытесняется при чтении. И вытеснятся будет либо кешлайн из таблицы, либо ещё более ненужный кешлайн. Т.е. полезного пространства таблица занимать не будет.
Если проще — любое чтение из памяти пробрасывает данные в кеш, а значит — попадает в рандомный бакет, где лежит наше значение из таблицы. И это значение из таблицы — вытесняется. Не вытеснится оно ТОЛЬКО тогда, когда будет горячее самого холодного. А что это значит? Это значит то, что оно используется часто. А значит — оно уже даёт профит.
Нужно понять базовую вещь — таблица либо выкидывается из памяти, либо даёт профит. Какие-то варианты есть тогда, когда мы читаем данные ТОЛЬКО в рамках определённого датасета и этот датасет примерно равен ширине кеша. Это очень, очень редкий кейс. В любом случае почти всегда(даже в близких этому кейсах) читаются левые данные, а значит — 1way всегда будет временный.
Таким образом — в 99+% случаев может быть 2кейса. Таблица используется редко — оно вытесняется из кеша сразу же, при чтении новых данных(любых). Таблица используется часто, но тогда она действительно лочит место в кеше, но в этом случае — она даёт профит. Ведь она во много раз быстрее деления.
Таким образом, даже если у вас есть нужные данные(которые вытеснит эта таблица) — они вытеснятся в л2, но у л2 летенси меньше, чем у дива. Вы получите деградацию, но в 12тактов, с дивом в 15.
Если вы хотите спросить «а если мои данные читаются чаще, чем исполняется див — почему ты считаешь одно чтение за одну операцию» — очень просто. Ведь если ваша программа читает нужны данные чаще, чем считает по таблице — ваши нужные данные ВСЕГДА(за исключением очень редких кейсов, но об этом я уже говорил выше) будет в кеше.
Вы собираетесь тупо складывать летенси инструкций исполняющихся на разных портах?
Мне лень комментировать эту откровенную ахинею, всё равно читать некому.
Но я спрошу ещё раз. Вам задали вопрос( не про летенси, не про порты и прочую кейворды, которые вы пастите мне из гугла). Вопрос звучал так:
На самом деле инструмент не принимает во внимание летенси не только кешей, но и дива. Почему вы здесь засыпались? Причины, хотя причин нет — я жду оправданий.
Тут нет никаких портов, никакого складывания летенси. Тут есть чёткий вопрос, почему наш эксперт всё напутал? Я продолжаю ждать оправданий.
без истерик и ругани, расписать как вы видите этот пример и почему вдруг вы выкидываете кеши/доступы к памяти из картины.
Никаких истерик и ругани нет — очередной враньё. Вам задали вопрос(и не один) и каждый из них вы проигнорировали. Отвечать что-то вменяемое клоуну, который просто каждое сообщение выкатывает новый тезис, который состоит из рандомного набор кейвордов из гугла — мне надоело.
Я могу в очередной раз констатировать — балабол. Ведь мы так и не узнали, почему вы ну учли то, что тулза не учитывает не только летенси кешей, но и инструкций. Человек, который понимает тему — никогда такую ахинею не напишет. НИКОГДА.
Внезапно вспоминаем, что этот инструмент не принимает во внимание летенси кешей,
На самом деле инструмент не принимает во внимание летенси не только кешей, но и дива. Почему вы здесь засыпались? Причины, хотя причин нет — я жду оправданий.
Т.е. мы имеем дела не явно некомпетентным трепачём, который игнорирует всё, что ему пишут — плюёт в лицо и мне и публике, пусть большинство этого и не понимают.
Я нормально написал множество раз, что я увидел в ответ? Игнорирование. Что там по манерам? Как это называется? Вы в край обнаглели, вы пользовались моими манерами, вы на этом паразитируете. Вы пишите бред в надежде, что оппонент вас не спрос, ведь это «грубо». Всегда можно врать.
В любом случае, мне это неинтересно. Я жду ответов на мои вопросы.
И где же у нас в коде множественные последовательные записи в кеш с шагом в 64 байта?
Так, ну пошла полная ахинея, будем действовать иначе. Раз наш оппонент игнорирует всё, и пытается выехать на на вранье и полностью неадекватен — я докажу, что он треплобалаболврун. Начнём.
Block Throughput: 14.00 Cycles
Внезапно вспоминаем, что этот инструмент не принимает во внимание летенси кешей,
Чёткое объяснение. Почему здесь есть рассуждения о летенси кеша, но нет рассуждений о летенси дива? Почему это обстоятельство куда-то пропало? Почему эксперт не сказал об этом, почему вместо правильного определения — эксперт дал неправильное?
Ваш подробный разбор не стоит и выеденного яйца, потому что вы разбираете не пример из статьи, а что-то из своей головы.
Вам задали вопрос выше — вы сели в лужу. Вы не предоставили ни единого примера и никак не обосновали свои обвинения.
Внезапно вспоминаем, что этот инструмент не принимает во внимание летенси кешей, смотрим на летенси.
Ещё раз вам повторю — вы нихрена не понимаете и несёте откровенную ахинею. Никакое летенси ни на что не влияет, вычисления не являются latency-bound задачей.
И самое главное, да, вас тут никто не поймает, но — я очередной раз покажу публике ваш уровень. Спорщик пытается юлить в сторону летенси, делая вид, что он не первый раз видит эти цифры, но — вот ведь незадача, у деления тоже есть летенси и 14тактов — это трупут( и тут даже написано это).
Инструмент не принимает во внимание летенси кешей, мало того, что это полная ахинея, дак к тому же ещё куда-то потерялось летенси дива. Куда? Ведь его летенси инструмент так же не принимает во внимание?
Ой, опять у нас какие-то проблемы. Почему же? Может потому, что не нужно писать рандомные фразы в ответ?
В любом случае — я уже всё сказал. Хотите играть в эту клоунаду — играйте. Впаривать наивным людям, с умным видом, ахинею — хорошее занятие, удобное занятие. Особенно на те темы, в которых мало кто разбирается. Продолжайте.
Данный вывод сходится с выводом из статьи «Станет ли быстрее с таким кешированием единиц или нет — непонятно:<и далее по тексту> может стать лучше<...>может ухудшиться». (Я вообще удивлён, что вы пытаетесь спорить с таким выводом!).
Подобные выводы не имеют смысла. И опять же, глупая попытка врать. Куда вы потеряли все остальные тезисы? Про «тратить 1кб памяти»? Расскажите мне о том, как оно тратит 1кб памяти. Что же вы не пытаетесь?
Расскажите мне про 2-4раза. Что же вы не рассказываете?
И как только вы сели в лужу со всем, чем только можно — вы пытаетесь юлить в сторону общих фраз.
Возможно специалист вы и компетентный, но из разговора следует обратное.
Эта клоунада. Я вас поймал уже с десяток раз, а вы меня ноль. Вы пытаетесь юлить и врать, на чём я так вас раз 10 поймал. Ответов вразумительных от вас последовало ровно ноль.
Но ничего, продолжайте, как я уже говорил — тему мало кто понимает и врать людям в глаза — ваша основное занятие, авось никто не заметит — никто и не замечает. Я даже шанс вам дал слиться по-тихому — обвините меня в грубости.
Опять враньё, опять ноль аргументации. Опять попытка врать в надежде, что публике будет лень читать мой подробный разбор. Мне достаточно спросить:
Вы додумываете факты которых в примере не было
Где, покажите. Почему вы не показали ни одного примера?
И далее ответа не будет, как его не было и сейчас. Ведь никаких додумываний фактов там нет — это враньё. А вот я уже много раз вас поймал на этом самом додумывании, подмене тезисов, откровенном вранье, игнорировании и прочем. И я могу это показать, в отличии от вас.
Хорошо, возьмём пример, который будет понятен всем.
Разработчики оптимизаторов имеют мало отношения к оптимизациям? Я вам не верю.
Это ответ на моё ответ на:
Люди, которые разрабатывают компиляторы, пишут книги на эту тему и защищают сложные теории, говорят, что в современном мире производительность системы ограничена не скоростью процессора, а зачастую работой с памятью:
И вы тут можете заметить то, о чём говорил я. Человек пытается врать, т.е. вначале он говорил об одном, а потом «разрабатывают компиляторы» пропали и появились «Разработчики оптимизаторов».
И мало того, я даже на эти «Разработчики оптимизаторов» ответил, но что мы видим? Видим игнор и очередное враньё.
Так в этом и посыл: «Не делайте преждевременных оптимизаций».
Зачем вы пытаетесь врать и дёргать фразы из контекста? Там написано то, что если убрать таблицу и заменить её на деление — это не будет иметь смысла и вам объяснили почему. У вас получится x * (1 / m), что попросту не имеет смысла.
В этом ваша проблемы — вы не понимает того, о чём пишите. Это касается всего, и бездумное пасты «тактов» и из таблицы, и обвинение кода в непонятности, который понятен всем, кто имел отношение к оптимизации вычислений.
Вы говорите, что бездумное выключение оптимизацией компилятора, вместо исправления ошибок, это ОК? Или вы спорите ради спора?
Опять какое-то враньё. Где я говорил подобное? Покажите мне.
Разработчики оптимизаторов имеют мало отношения к оптимизациям? Я вам не верю.
Мне не нужно верить. Есть факты, которые мною доказаны: а) вы не понимаете тему, б) вы не понимаете матчасть. Поэтому извините, но ваши рассуждения об оптимизациях, тактах, понятности кода — стоят ноль.
И самое важное — мы опять видим враньё. Вы выдернули какую-то фразу из контекста, в которой вообще не говорится об «Разработчики оптимизаторов».
Давайте я перечислю вам всё ваше враньё.
Первое — оптимизации оптимизациям рознь. Один вид оптимизаций требует совершенного другого понимания, нежели другой. Как бы вам попроще объяснить. Берём llvm, в котором( на уровне ир, т.е. почти все) почти все оптимизации являются обобщёнными, т.е. они никак не учитывают таргет. Да, частично и в каком-то виде они могут это делать, но это крохи. В этом их смысл, ведь таргетов много.
И все людям, которые разрабатывают эти обобщённые оптимизации нет смысла, и попросту невозможно понимать и знать какой-то таргет. Таргет — это уровень кодогена, а там какими-то оптимизациями еле пахнет.
Так же, есть просто примитивные оптимизации и таких 90%. Всякие реплейсы по паттерну — замена циклов копирования на мемсет, замена циклов подсчёта бит на popcount и прочее и прочее. Это всё так же не имеет никакого отношения к тому, о чём говорил я.
Люди, которые разрабатывают компиляторы
Враньё второе. Вы написали это, а после «Разработчики оптимизаторов». Зачем? Разработчик компилятора — это далеко не только разработчик оптимизатора, вернее в подавляющем большинстве случаев это не так.
пишут книги на эту тему и защищают сложные теории
В том то и дело, что пишут книги, защищают теории. Но совершенно на другие темы, и опять же — они не занимаются разработкой оптимизаций.
говорят, что в современном мире производительность системы ограничена не скоростью процессора, а зачастую работой с памятью
Это очередной пример того, как человек где-то услышал какую-то фразу и повторяет её везде. Зачем? Это ничего не стоит и ничего не значит. Это общие фразы, которые никакого отношения к конкретному случаю не имеют.
В конкретном случае мы можем почитать — во что и как у нас упирается производительность и для этого нам не нужны общие фразы. Вы не можете, вы не знаете, вы не понимаете — именно поэтому вы и кидаетесь общими фразами.
Надо отметить, что вещи вы порой говорите правильные. НО их практически не видно из-за вашей агрессии и желания поспорить ради спора. Жаль, ведь можно было бы более продуктивно обсудить этот пример. Смотрите:
Вы мне не покажите «неправильно», в этом и проблема. Это не спор ради спора, не агрессия — это лишь ваши попытки свести дискуссию куда-то не туда.
Вы не можете обсуждать этот пример — вы некомпетентны. И вам это не нравиться. Вы хотите, чтобы я принял ваши попытки ехать в сторону общих враз и поверий — нет, этого не будет.
Вы: Out Of Order Execution увидит что доступ к памяти и заранее постарается подтянуть данные в кеш, зачастую сводя на нет простои
Вы не понимаете того, о чём говорите. Зачем вы мои слова выдаёте какой-то малограмотный бред?
Я: Это не гарантия. Если этот код будет стоять в начале одной из веток, branch predictor мог бы сплоховать и мы получили бы простой в полной мере.
Опять — вы не понимаете того, о чём говорите. Ну и тут прослеживается явная попытка съехать с темы. В рамках конкретного примера можно почитать — будет там гарантия, либо нет. И ваши общие фразы — ничего не стоят.
Вы: Вы взяли количество тактов для целочисленного деления, вместо деления double
Нет, опять враньё. Вы не просто взяли не то, вы неправильно даже разделили 25+ на 5, не говоря уже о том, что там будет 4-5раз( в рамках вашей логики), но никак не 2-4. Т.е. тут проблема даже с банальной арифметикой.
Тут вы опять пытаетесь врать. Это не ваша основная проблема — ваша проблема( основная) в том, что вы пытаетесь кидаться какими-то цифрами, значения которых вы не понимаете. Зачем?
Я: Это просто неудачное название для деления на слайде. Да и современные процессоры, деление делают достаточно быстро. Так FDIV на Ivy Bridge занимает 10-24 тактов
Вот опять мы видим очередную глупость. Никакие процессоры не делают никакое деление быстро — это невозможно. Второе, вы опять пытаетесь кидаться непонятными вам цифрами, хотя об этом я уже говорил выше.
И ладно, я даже не требую с вас понимания, но. Даже не понимания проблемы, любой, что хоть раз видел живот код — никогда не сошлётся на fdiv. Вывод? Вы даже кода не видели, но зачем вы куда-то лезете?
Но я вам сообщаю — fpu сдохло во времена core2, а значит все fdiv«ы тоже. Такие дела.
Хотя о чём это я, 10-24такта — это в 20-48раз медленнее чтения из l1d.
Разберитесь в теме перед тем, как о чём-то рассуждать. Да, никто тут вас не поймает и можно с умным видом нести откровенный бред. И меня всегда можно заминусовать, но. Это ничего не изменит. Если вы хотите действительно говорить полезные вещи — изучите тему, а если нет — продолжайте в том же духе. Шансы на изобличение крайне малы.
Я хотел разобрать и то, что вы там наговорили на тему форсинлайна, но мне стало лень. И до сих пор лень. На самом деле везде, где вы пытаетесь говорить о матчасти — выходит полный бред.
А я про количество элементов и не писал. Я писал про их _размер_ (в байтах) по отношению к размеру кеш-линии (тоже в байтах).
Вы писали про какую-то «эффективность вытеснения», которая очень слабо связана и с первым и со вторым и с третьим. И абсолютно неважно что там, элементы, размеры в байтах, отношения — это одно и то же, а точнее то, что не имеет никакого отношения к делу. Вернее имеет, но крайне опосредованное.
Просто при расчёте того, на сколько кеширующая таблица зафлудит кеш нужно считать не среднее число используемых элементов в некий короткий промежуток времени (скажем ~100-1000 тактов)
Во-первых, зачем вы мне об этом рассказываете, когда я сделал до вас? Я ведь не зря там сделал уточнение.
Второе — промежуток времени никого не интересует и ничего не значит. И вам уже объяснили почему.
При таблице в 400 байт (100 флоатов) и 10 случайно распределенных релевантных (на промежутке в 100 тактов) элементов, на эти 100 тактов, будет забито 384 байта кеша, а не 40 байт.
Не будет.
Выходит, что при 10% использовании таблицы кеш будет зафлужен на ~100% размера таблицы.
Не будет.
Я не беру самый неблагоприятный случай, когда достаточно что бы каждый 16й элемент был задействован. Я беру именно 10% случайно распределенных элементов. Конечно, могут быть и более благоприятные, но проблема именно в том, что столкнуться с неблагоприятным очень легко.
Вы продолжаете повторять одно и то же, игнорирую то, о чём вам говорят. Но я повторю в сотый раз.
Абсолютно неважно то, сколько и чего вы там насчитали — это не имеет отношения к реальности. Для того, чтобы вытеснились не данные из таблицы, а левые данные — надо обеспечить то, чтобы эти данные были холоднее. А раз они холоднее — они не нужны, а значит все эти рассуждения не имеют смысла.
Если у нас есть горячие данные в кэше, то абсолютно неважно сколько вы там будите читать, хоть каждый 16элемент — занимать это будет ровно ОДИН кешлайн. Хоть там будь терабайт табилцы — это ничего не изменит.
И только тогда, когда ваши данные из таблице станут горячее других данных — в кеше будут оставаться данные из таблице, но в этом случае таблица станет узким местом, а раз таблица быстрее вычислений — таблица себя оправдает.
С тех самых пор, как появились потоки и само понятие потокобезопасности, как следствие — то есть с C++11. Все классы потокобезопасны (на базовом уровне), если не оговорено обратное; в частности, здесь применимо следующее правило:
К чему это написано и спащена цитата ниже? Спащенная цитат имеет отношение к нюансам реализации. «Если вы используете потоки в реализации — вы должны сами обеспечивать их безопасность», но из этого никак не следует то, что строка mt-safe.
В C++ нет понятия «COW-строка», есть просто «строка».
Меня мало интересуют тезисы, которые рождаются постфактум. В рамках статьи говорилось о велосипедах, вот и говорите о них. Зачем вы постоянно придумываете новые истории?
COW — это один из возможных видов реализации, про которые пользователь ничего знать не обязан, ибо инкапсуляцию никто не отменял.
Неверно. Вы можете мне попытаться показать, где в статье говорилось об cow-реализациях std::string. Да, там приводились в примеры cow-реализации std::string(старого), но ими дело не ограничивалось. std::string там приведён на правах истории, как объяснение того — почему раньше так было в std::string.
Да что говорить — там даже эта строка есть:
Начиная с C++11 COW строчки запрещены в стандарте. Там наложены специальные условия на строчку, что COW реализовать невозможно. Все современные имплементации стандартных библиотек не имеют COW строк.
Т.е. автор явно не сравнивает std::string и std::string. Это следует и из множество других мест.
Связанные с COW проблемы потокобезопасности лежат исключительно на разработчиках стандартной библиотеки.
Осталось только понять — откуда вы взяли всю эти историю со стандартной библиотекой? Сами придумали? А какое отношение ваши придумки имеют к теме?
Автор дал определение «cow-велосипед», который никаким образом не является стандартной библиотекой и не является имплементацией std::string.
На мой вкус, если называешь свой велосипед именем стандартного контейнера
С каких пор какой-то стандарт приватизировал имя string? Оно было ещё тогда, когда этого стандарта в проекте не было, как и С++.
Иначе, это будет мина замедленного действия, на которую с большой вероятностью, кто ни-буть наступит.
Это иначе и нужно писать в причинах, а не всё остальное. Вот и напишите его, а всё остальное удалите. Раз вы не можете вести дискуссию в рамках прежних тезисов и постоянно пытаетесь их поменять.
Что бы этого избежать, прийдется постоянно держать в голове, что в проекте своя реализация string, копии которого нельзя передавать в потоки.
Чтобы этого избежать — постоянно надо держать в голове, что просто замувить что-то нельзя. Дальше что? Я что-то не вижу от вас тех же рассуждений в адрес move?
Согласитесь, не плохая подстава для новых людей на проекте.
Я обсуждаю тему в рамках тезисов определённых в статье. Хотите использовать другие тезисы — поменяйте их в статье.
Что бы работало вытеснение, нужно что бы те объекты, к которым нет обращения могли быть вымыты из кеша.
Это не имеет смысла. Зачем вы пытаетесь общие вещи натянуть на конкретный случай? Общие вещи не относятся к данному случаю — ведь они на то и общие.
В результате эффективность вытеснения тем ниже, чем больше размер кеш линии по отношению к размеру элемента.
Неверно. Абсолютно неважен размер элемента — память считается не в элементах.
Если размер кеш линии уже порядка размера всего кешируемого массива — вытеснение почти не работает.
Работает.
В результате может получится, что «несколько соседних элементов» — это практически весь кешируемый массив и есть.
Может, но из этого ничего не следует. Это явно не этот массив, да и даже если бы был этот — это ничего не меняет.
В случае с массивом на 100 флоатов (400 байт) и линией на 64 байта, при случайном доступе достаточно задействовать примерно 8-10 флоатов из 100 что бы исключить вытеснение и забить кеш.
Неверно. Во-первых, как я уже говорил — это попытка натянут сову на глобус.
Во-вторых, это ничего не меняет, ведь будет вытеснятся тот кешлайн, в который было прочитано предыдущие значение. Описанное вами может случится только в том случае, если эти 8-10 элементов ГОРЯЧЕЕ ДРУГИХ данных, а значит — другие данные объективно менее важные. А то, что ненужно — то неважно. И есть ли ненужны данные в кэше, либо их нет — абсолютно неважно.
Повторю ещё раз. Тут есть два основных тезиса Первый общий и предпосылки к нему формулируются так «чтение какого угодно куска памяти — триггерит чтение куска данных шириной в кешлайн»", а далее — все вытекающие. Но а) этих вытекающих почти нет, б) они итак есть везде и эта «таблица» — не исключение.
Второй тезис «ненужные данные в кэше» — в кэше не может быть «Ненужных данных», даже если попутно с нужными кэш забьётся ненужными, то в любом случае — это данные нужнее всех остальных, ведь они читаются чаще.
Подобное может проявиться только в очень-очень редких случаях, когда у нас есть некий датасет, который тютелька в тютельку упирается в ширину кэша, при этом он настолько же горяч, как и данная таблица. Но даже тут есть проблемы, ведь у нас есть l2, который всё равно дешевле показанных 20+тактов.
(при условии, что наша реализации должна соответствовать стандарту C++, которая не запрещает передавать копии строки в другие потоки)
А зачем вы пытаетесь придумывать какие-то новый условия? Никто не сравнивал реализацию std::string с COW и без COW. Сравнивали COW-велосипед, а теперь вы пытаетесь превратить COW-велосипед в «std::string с COW». Как так получилось?
COW-велосипед не должно интересовать то, какая там реализация должна быть в стандарте. Особенно в контексте того, что у COW совершенно другая терминология и семантика.
Быстрее чего? Какое деление? Откуда оно взялось? О чём вы вообще говорите?
В вашем примере нет никакого деления, нет никакой векторизации. Вам об этом сообщили — вы всё перепутали. Вам нужно это осознать и сделать соответствующие выводы.
Ваш пример — это 1в1 то, что критиковал автор, а именно — кэширование 1/n, а после использование этого коэффициента для замены деления на умножения. При его вычисление НЕ ИСПОЛЬЗУЕТ НИКАКИХ " выполнять на лету при помощи векторных инструкций. ", вообще никаких векторных инструкций.
Никакого отношения ваш пример к векторизации деления не имеет. Повторюсь уже в 3-4раз.
Я уже ответил на это выше. Ничего не мешает сделать сделать метод copy для строки.
И на пользователя переложить нельзя, потому что это «кишки».
Тут и не нужны никакие кишки. Вызов clone/copy не является кишками. Шарить «cow-копии» строки между тредами нельзя, так же как и ссылки, так же как и мувить из другого треда и прочее.
Да хоть мильён — какая разница? Это свойство памяти — она не читается по 1/2/4/8 байт — она читается кешлайнами и любая память читается только через кэш(за исключением nt). Это не свойство это таблицы — это глобальное свойство, которое распространяется на все чтения в программе.
На любое чтение — процессор прочитает кешлайн. Если этот кешлайн далее не нужен — он вытеснится чтением другого кешлайна. И это, ровным счётом, ни на что не повлияет.
На самом деле кеширование результата операции целесообразно только для деление на небольшое число.
Это абсолютно неважно. Число может быть каким угодно — определяющим является их кол-во, а не то «большое» оно, либо нет.
Кроме того доступ к закешированным данным плохо векторизуется.
Неверно. Можно хранить целые вектора, либо есть броадкаст. Да что там далеко ходить — по вашей ссылки есть пример:
__m128 _k = _mm_set1_ps(1.0f / p);
Это именно одно число с «броадкастом», ничего не мешает подставить сюда число из таблицы.
Никаких проблем нет, если нам нужно и умножать на последовательность чисел — она спокойно читается.
Таблица таблице рознь, но до — таблица не векторизуется и они почти полностью бесполезны при векторизации.
Если деление настолько массовая операция, то наиболее оптимально будет ее выполнять на лету при помощи векторных инструкций. Нашел пример с умножением по модулю:
Этот пример никакого отношения к тому, о чём вы говорите — не имеет. Это оптимизация деления на констанату, которая вычисляется не «при помощи векторных инструкций», а банальным делением, а потом используется как константа при вычислениях.
Если у вас константа одна и её можно предрассчитать, то проще предрассчитать, но не всегда и не везде. К тому же — есть множество кейсов, где длинна предвычисление будет стоит дорого, неоправданно дорого.
В данном примере просто векторизуется операция int(float(d)/float(p))*p. Причём очень колхозно. И самое интересное — этот же пример вас опровергает. Это деление будет исполнятся значительную часть от самого цикла. 10-20+% и это лишь потому, что флоат-деление достаточно халявное. К тому же флоаты тут явно не подходят, ведь их точности на инт не хватит — нужны даблы. Там уже ситуация будет куда хуже.
К тому же, не стоит забывать, что данная реализация слишком кастыльная — там почти всё время тратится на касты. Будь это изначально флоаты/даблы — мы бы потеряли не 10-20%+, а все 100%+.
И нам бы пришлось выносить это из цикла, т.е. кэшировать вычисление.
Точно так же, как и с дефолтным std::string. Тут можно пытаться ехать в сторону «а как нам пошарить две одинаковые строки между тредами», но это так же не является проблемой. Решается одним методом, который делает реальную копию.
Смысл в том, что реальность она сложнее. В ней нет такого понятия как «узкое место — память» — у памяти есть совершенно разные места, которые могут быть узкими.
Как мы уже выяснили — есть две основные метрики — летенси и трупут. Причём они не определяются примитивными определениями уровня «последовательное — трупут, а рандомное — летенси», как многие делают. Это фундаментальное-противоположные вещи, с совершенно разными свойствами.
Всё это можно определить через уровень параллельности конкретной задачи. И в зависимости от этого уровня — всё может очень сильно меняться. Допустим, как я уже говорил, вычисления — это, в основном, хорошо распараллеливаемые задачи( не нужно ограничивать параллельность потоками ОС). Это задачи упирающиеся в трупут — нет смысла приводить какие-то цифры, которые никакого отношения к данному кейсу не имеют.
Кейсы с хорошим уровнем параллелизма могут быть и memory-bound, и какими угодно. Это не значит, что они упираются в вычисления.
В кеше хранятся активные данные. Если данные неактивные — они ненужны. Это ничего не изменит. Если мы не хотим вытеснять данные из кеша — мы вообще НИЧЕГО не должны читать из памяти(кроме активного датасета). Любое чтение — вытесняет нужны данные.
Естественно, что никто и никогда не использует весь кеш, именно поэтом в нём останется это один уровень, который будет забиваться временными данными. И это абсолютно ни на что не повлияет.
И опять же, всё неправильно — активный датасет в несколько мегабайт вообще никак не зависит от llc, от l2 — влезет в l3 — зависит от l3.
В данном случае меньшие кеши имеют только одно применение — кешировать некие часто используемые данные и тут будет такое же вытеснение одного way.
Какое влияние кеши меньшие кеши могут оказывать только тогда, когда наша задача состоит из подзадач, в рамках которой много раз перечитываются данные в рамках малого датасета. Такого очень мало.
Реально подобный случай — это банальная оптимизация скалярной лапши. Смысл очень просто. Когда мы попадаем в тот же l2 — данные( а именно кешлайн) мигрируют в l1d, а т.к. скалярный лапша читает данные по 1/2/4/8 байт, то в рамках последовательного чтения — мы перечитываем этот кешлайн множество раз, до 64. Если бы он не мигровал в l1d, то мы бы множество раз читали куски из l2, что явно хуже
С учётом некой параллельности( в простонародье prefetch) — нам желательно читать сразу несколько кешлайнов. На самом деле тут и l1d не нужен — хватит буферов, но мы не об этом.
И казалось бы — мы нашли подходящий кейс, но нет — ему не нужен весь l1d — ему хватит десяток кешлайнов. Остальной кеш ненужен и ни на что не влияет.
Всё это к чему? А к тому, что очень сложной придумать кейс, в котором 1way будет не временным. Всё то, что кажется подходящим — лишь кажется.
На самом деле всё как раз наоборот — основная проблема таблицы не в том, что она захламляет кеш — нет. Это почти всегда не так. Проблема её именно в том, что её может не быть в кеше, а значит — мы словим деградацию. Но на это можно так же забить. Если у нас таблица настолько ненужная, что её нет в кеше, то её производительность вообще никак не влияет на программу.
И вот у нас есть выбор. Даже если случится так, что мы проиграем в паре вызовов диву, но — это будут те случаи, которые никак не влияют на производительность нашей программы. А вот в случае частого использования — она будет в кеше, не будет его тратить( за очень-очень редкими исключениями), но при этом будет давать профит. А раз она используется часто, то и влияние на производительность нашей программы оказывает весомое.
В конечном итоге, к чему это? Всё очень просто — таблица( если она имеет реальный профит, а это имеет, да и ещё какой( до пары порядков профита)) — лучшее решение.
Тут мы видим попытку натянуть свои слабые представления на реальность. Я бы мог тут придраться к «memory address» в контексте всех тех проблем, которые вызывают тот факт, что адресов два и как это решается и почему там не memory address. Я бы мог придраться к «смотрю в книгу — вижу фигу», ведь человек выше кидался в меня таблицей по кешам, где чёрным по белом написано 8-way, но у него 4. Всё это неважно.
32kb кэша — это 512 кешлайнов, при 8-way — это 64бакета.
Таким образом проход под массиву из 2к в среднем попадёт в 32бакета, что вытеснит 2кб. Мало того, что вы не умеете делить 25+ на 5, вы ещё и не смогли правильно посчитать ширину таблицы.
Но, в чём смысл — в любом кейсе, кроме одного(когда мы работаем на датасете шириною в кеш) — 1way никогда не используется, т.е. он временный и вытесняется при чтении. И вытеснятся будет либо кешлайн из таблицы, либо ещё более ненужный кешлайн. Т.е. полезного пространства таблица занимать не будет.
Если проще — любое чтение из памяти пробрасывает данные в кеш, а значит — попадает в рандомный бакет, где лежит наше значение из таблицы. И это значение из таблицы — вытесняется. Не вытеснится оно ТОЛЬКО тогда, когда будет горячее самого холодного. А что это значит? Это значит то, что оно используется часто. А значит — оно уже даёт профит.
Нужно понять базовую вещь — таблица либо выкидывается из памяти, либо даёт профит. Какие-то варианты есть тогда, когда мы читаем данные ТОЛЬКО в рамках определённого датасета и этот датасет примерно равен ширине кеша. Это очень, очень редкий кейс. В любом случае почти всегда(даже в близких этому кейсах) читаются левые данные, а значит — 1way всегда будет временный.
Таким образом — в 99+% случаев может быть 2кейса. Таблица используется редко — оно вытесняется из кеша сразу же, при чтении новых данных(любых). Таблица используется часто, но тогда она действительно лочит место в кеше, но в этом случае — она даёт профит. Ведь она во много раз быстрее деления.
Таким образом, даже если у вас есть нужные данные(которые вытеснит эта таблица) — они вытеснятся в л2, но у л2 летенси меньше, чем у дива. Вы получите деградацию, но в 12тактов, с дивом в 15.
Если вы хотите спросить «а если мои данные читаются чаще, чем исполняется див — почему ты считаешь одно чтение за одну операцию» — очень просто. Ведь если ваша программа читает нужны данные чаще, чем считает по таблице — ваши нужные данные ВСЕГДА(за исключением очень редких кейсов, но об этом я уже говорил выше) будет в кеше.
Мне лень комментировать эту откровенную ахинею, всё равно читать некому.
Но я спрошу ещё раз. Вам задали вопрос( не про летенси, не про порты и прочую кейворды, которые вы пастите мне из гугла). Вопрос звучал так:
Тут нет никаких портов, никакого складывания летенси. Тут есть чёткий вопрос, почему наш эксперт всё напутал? Я продолжаю ждать оправданий.
Никаких истерик и ругани нет — очередной враньё. Вам задали вопрос(и не один) и каждый из них вы проигнорировали. Отвечать что-то вменяемое клоуну, который просто каждое сообщение выкатывает новый тезис, который состоит из рандомного набор кейвордов из гугла — мне надоело.
Я могу в очередной раз констатировать — балабол. Ведь мы так и не узнали, почему вы ну учли то, что тулза не учитывает не только летенси кешей, но и инструкций. Человек, который понимает тему — никогда такую ахинею не напишет. НИКОГДА.
На самом деле инструмент не принимает во внимание летенси не только кешей, но и дива. Почему вы здесь засыпались? Причины, хотя причин нет — я жду оправданий.
Т.е. мы имеем дела не явно некомпетентным трепачём, который игнорирует всё, что ему пишут — плюёт в лицо и мне и публике, пусть большинство этого и не понимают.
Я нормально написал множество раз, что я увидел в ответ? Игнорирование. Что там по манерам? Как это называется? Вы в край обнаглели, вы пользовались моими манерами, вы на этом паразитируете. Вы пишите бред в надежде, что оппонент вас не спрос, ведь это «грубо». Всегда можно врать.
В любом случае, мне это неинтересно. Я жду ответов на мои вопросы.
Так, ну пошла полная ахинея, будем действовать иначе. Раз наш оппонент игнорирует всё, и пытается выехать на на вранье и полностью неадекватен — я докажу, что он
треплобалаболврун. Начнём.Чёткое объяснение. Почему здесь есть рассуждения о летенси кеша, но нет рассуждений о летенси дива? Почему это обстоятельство куда-то пропало? Почему эксперт не сказал об этом, почему вместо правильного определения — эксперт дал неправильное?
Вам задали вопрос выше — вы сели в лужу. Вы не предоставили ни единого примера и никак не обосновали свои обвинения.
Ещё раз вам повторю — вы нихрена не понимаете и несёте откровенную ахинею. Никакое летенси ни на что не влияет, вычисления не являются latency-bound задачей.
И самое главное, да, вас тут никто не поймает, но — я очередной раз покажу публике ваш уровень. Спорщик пытается юлить в сторону летенси, делая вид, что он не первый раз видит эти цифры, но — вот ведь незадача, у деления тоже есть летенси и 14тактов — это трупут( и тут даже написано это).
Инструмент не принимает во внимание летенси кешей, мало того, что это полная ахинея, дак к тому же ещё куда-то потерялось летенси дива. Куда? Ведь его летенси инструмент так же не принимает во внимание?
А что же у нас там по трупуту кешей?
Ой, опять у нас какие-то проблемы. Почему же? Может потому, что не нужно писать рандомные фразы в ответ?
В любом случае — я уже всё сказал. Хотите играть в эту клоунаду — играйте. Впаривать наивным людям, с умным видом, ахинею — хорошее занятие, удобное занятие. Особенно на те темы, в которых мало кто разбирается. Продолжайте.
Подобные выводы не имеют смысла. И опять же, глупая попытка врать. Куда вы потеряли все остальные тезисы? Про «тратить 1кб памяти»? Расскажите мне о том, как оно тратит 1кб памяти. Что же вы не пытаетесь?
Расскажите мне про 2-4раза. Что же вы не рассказываете?
И как только вы сели в лужу со всем, чем только можно — вы пытаетесь юлить в сторону общих фраз.
Эта клоунада. Я вас поймал уже с десяток раз, а вы меня ноль. Вы пытаетесь юлить и врать, на чём я так вас раз 10 поймал. Ответов вразумительных от вас последовало ровно ноль.
Но ничего, продолжайте, как я уже говорил — тему мало кто понимает и врать людям в глаза — ваша основное занятие, авось никто не заметит — никто и не замечает. Я даже шанс вам дал слиться по-тихому — обвините меня в грубости.
Где, покажите. Почему вы не показали ни одного примера?
И далее ответа не будет, как его не было и сейчас. Ведь никаких додумываний фактов там нет — это враньё. А вот я уже много раз вас поймал на этом самом додумывании, подмене тезисов, откровенном вранье, игнорировании и прочем. И я могу это показать, в отличии от вас.
Хорошо, возьмём пример, который будет понятен всем.
Это ответ на моё ответ на:
И вы тут можете заметить то, о чём говорил я. Человек пытается врать, т.е. вначале он говорил об одном, а потом «разрабатывают компиляторы» пропали и появились «Разработчики оптимизаторов».
И мало того, я даже на эти «Разработчики оптимизаторов» ответил, но что мы видим? Видим игнор и очередное враньё.
Зачем вы пытаетесь врать и дёргать фразы из контекста? Там написано то, что если убрать таблицу и заменить её на деление — это не будет иметь смысла и вам объяснили почему. У вас получится x * (1 / m), что попросту не имеет смысла.
В этом ваша проблемы — вы не понимает того, о чём пишите. Это касается всего, и бездумное пасты «тактов» и из таблицы, и обвинение кода в непонятности, который понятен всем, кто имел отношение к оптимизации вычислений.
Опять какое-то враньё. Где я говорил подобное? Покажите мне.
Мне не нужно верить. Есть факты, которые мною доказаны: а) вы не понимаете тему, б) вы не понимаете матчасть. Поэтому извините, но ваши рассуждения об оптимизациях, тактах, понятности кода — стоят ноль.
И самое важное — мы опять видим враньё. Вы выдернули какую-то фразу из контекста, в которой вообще не говорится об «Разработчики оптимизаторов».
Давайте я перечислю вам всё ваше враньё.
Первое — оптимизации оптимизациям рознь. Один вид оптимизаций требует совершенного другого понимания, нежели другой. Как бы вам попроще объяснить. Берём llvm, в котором( на уровне ир, т.е. почти все) почти все оптимизации являются обобщёнными, т.е. они никак не учитывают таргет. Да, частично и в каком-то виде они могут это делать, но это крохи. В этом их смысл, ведь таргетов много.
И все людям, которые разрабатывают эти обобщённые оптимизации нет смысла, и попросту невозможно понимать и знать какой-то таргет. Таргет — это уровень кодогена, а там какими-то оптимизациями еле пахнет.
Так же, есть просто примитивные оптимизации и таких 90%. Всякие реплейсы по паттерну — замена циклов копирования на мемсет, замена циклов подсчёта бит на popcount и прочее и прочее. Это всё так же не имеет никакого отношения к тому, о чём говорил я.
Враньё второе. Вы написали это, а после «Разработчики оптимизаторов». Зачем? Разработчик компилятора — это далеко не только разработчик оптимизатора, вернее в подавляющем большинстве случаев это не так.
В том то и дело, что пишут книги, защищают теории. Но совершенно на другие темы, и опять же — они не занимаются разработкой оптимизаций.
Это очередной пример того, как человек где-то услышал какую-то фразу и повторяет её везде. Зачем? Это ничего не стоит и ничего не значит. Это общие фразы, которые никакого отношения к конкретному случаю не имеют.
В конкретном случае мы можем почитать — во что и как у нас упирается производительность и для этого нам не нужны общие фразы. Вы не можете, вы не знаете, вы не понимаете — именно поэтому вы и кидаетесь общими фразами.
Вы мне не покажите «неправильно», в этом и проблема. Это не спор ради спора, не агрессия — это лишь ваши попытки свести дискуссию куда-то не туда.
Вы не можете обсуждать этот пример — вы некомпетентны. И вам это не нравиться. Вы хотите, чтобы я принял ваши попытки ехать в сторону общих враз и поверий — нет, этого не будет.
Вы не понимаете того, о чём говорите. Зачем вы мои слова выдаёте какой-то малограмотный бред?
Опять — вы не понимаете того, о чём говорите. Ну и тут прослеживается явная попытка съехать с темы. В рамках конкретного примера можно почитать — будет там гарантия, либо нет. И ваши общие фразы — ничего не стоят.
Нет, опять враньё. Вы не просто взяли не то, вы неправильно даже разделили 25+ на 5, не говоря уже о том, что там будет 4-5раз( в рамках вашей логики), но никак не 2-4. Т.е. тут проблема даже с банальной арифметикой.
Тут вы опять пытаетесь врать. Это не ваша основная проблема — ваша проблема( основная) в том, что вы пытаетесь кидаться какими-то цифрами, значения которых вы не понимаете. Зачем?
Вот опять мы видим очередную глупость. Никакие процессоры не делают никакое деление быстро — это невозможно. Второе, вы опять пытаетесь кидаться непонятными вам цифрами, хотя об этом я уже говорил выше.
И ладно, я даже не требую с вас понимания, но. Даже не понимания проблемы, любой, что хоть раз видел живот код — никогда не сошлётся на fdiv. Вывод? Вы даже кода не видели, но зачем вы куда-то лезете?
Но я вам сообщаю — fpu сдохло во времена core2, а значит все fdiv«ы тоже. Такие дела.
Хотя о чём это я, 10-24такта — это в 20-48раз медленнее чтения из l1d.
Разберитесь в теме перед тем, как о чём-то рассуждать. Да, никто тут вас не поймает и можно с умным видом нести откровенный бред. И меня всегда можно заминусовать, но. Это ничего не изменит. Если вы хотите действительно говорить полезные вещи — изучите тему, а если нет — продолжайте в том же духе. Шансы на изобличение крайне малы.
Я хотел разобрать и то, что вы там наговорили на тему форсинлайна, но мне стало лень. И до сих пор лень. На самом деле везде, где вы пытаетесь говорить о матчасти — выходит полный бред.
Вы писали про какую-то «эффективность вытеснения», которая очень слабо связана и с первым и со вторым и с третьим. И абсолютно неважно что там, элементы, размеры в байтах, отношения — это одно и то же, а точнее то, что не имеет никакого отношения к делу. Вернее имеет, но крайне опосредованное.
Во-первых, зачем вы мне об этом рассказываете, когда я сделал до вас? Я ведь не зря там сделал уточнение.
Второе — промежуток времени никого не интересует и ничего не значит. И вам уже объяснили почему.
Не будет.
Не будет.
Вы продолжаете повторять одно и то же, игнорирую то, о чём вам говорят. Но я повторю в сотый раз.
Абсолютно неважно то, сколько и чего вы там насчитали — это не имеет отношения к реальности. Для того, чтобы вытеснились не данные из таблицы, а левые данные — надо обеспечить то, чтобы эти данные были холоднее. А раз они холоднее — они не нужны, а значит все эти рассуждения не имеют смысла.
Если у нас есть горячие данные в кэше, то абсолютно неважно сколько вы там будите читать, хоть каждый 16элемент — занимать это будет ровно ОДИН кешлайн. Хоть там будь терабайт табилцы — это ничего не изменит.
И только тогда, когда ваши данные из таблице станут горячее других данных — в кеше будут оставаться данные из таблице, но в этом случае таблица станет узким местом, а раз таблица быстрее вычислений — таблица себя оправдает.
К чему это написано и спащена цитата ниже? Спащенная цитат имеет отношение к нюансам реализации. «Если вы используете потоки в реализации — вы должны сами обеспечивать их безопасность», но из этого никак не следует то, что строка mt-safe.
Меня мало интересуют тезисы, которые рождаются постфактум. В рамках статьи говорилось о велосипедах, вот и говорите о них. Зачем вы постоянно придумываете новые истории?
Неверно. Вы можете мне попытаться показать, где в статье говорилось об cow-реализациях std::string. Да, там приводились в примеры cow-реализации std::string(старого), но ими дело не ограничивалось. std::string там приведён на правах истории, как объяснение того — почему раньше так было в std::string.
Да что говорить — там даже эта строка есть:
Т.е. автор явно не сравнивает std::string и std::string. Это следует и из множество других мест.
Осталось только понять — откуда вы взяли всю эти историю со стандартной библиотекой? Сами придумали? А какое отношение ваши придумки имеют к теме?
Автор дал определение «cow-велосипед», который никаким образом не является стандартной библиотекой и не является имплементацией std::string.
С каких пор какой-то стандарт приватизировал имя string? Оно было ещё тогда, когда этого стандарта в проекте не было, как и С++.
Это иначе и нужно писать в причинах, а не всё остальное. Вот и напишите его, а всё остальное удалите. Раз вы не можете вести дискуссию в рамках прежних тезисов и постоянно пытаетесь их поменять.
Чтобы этого избежать — постоянно надо держать в голове, что просто замувить что-то нельзя. Дальше что? Я что-то не вижу от вас тех же рассуждений в адрес move?
Я обсуждаю тему в рамках тезисов определённых в статье. Хотите использовать другие тезисы — поменяйте их в статье.
Это не имеет смысла. Зачем вы пытаетесь общие вещи натянуть на конкретный случай? Общие вещи не относятся к данному случаю — ведь они на то и общие.
Неверно. Абсолютно неважен размер элемента — память считается не в элементах.
Работает.
Может, но из этого ничего не следует. Это явно не этот массив, да и даже если бы был этот — это ничего не меняет.
Неверно. Во-первых, как я уже говорил — это попытка натянут сову на глобус.
Во-вторых, это ничего не меняет, ведь будет вытеснятся тот кешлайн, в который было прочитано предыдущие значение. Описанное вами может случится только в том случае, если эти 8-10 элементов ГОРЯЧЕЕ ДРУГИХ данных, а значит — другие данные объективно менее важные. А то, что ненужно — то неважно. И есть ли ненужны данные в кэше, либо их нет — абсолютно неважно.
Повторю ещё раз. Тут есть два основных тезиса Первый общий и предпосылки к нему формулируются так «чтение какого угодно куска памяти — триггерит чтение куска данных шириной в кешлайн»", а далее — все вытекающие. Но а) этих вытекающих почти нет, б) они итак есть везде и эта «таблица» — не исключение.
Второй тезис «ненужные данные в кэше» — в кэше не может быть «Ненужных данных», даже если попутно с нужными кэш забьётся ненужными, то в любом случае — это данные нужнее всех остальных, ведь они читаются чаще.
Подобное может проявиться только в очень-очень редких случаях, когда у нас есть некий датасет, который тютелька в тютельку упирается в ширину кэша, при этом он настолько же горяч, как и данная таблица. Но даже тут есть проблемы, ведь у нас есть l2, который всё равно дешевле показанных 20+тактов.
Слишком притянуто за уши.
А зачем вы пытаетесь придумывать какие-то новый условия? Никто не сравнивал реализацию std::string с COW и без COW. Сравнивали COW-велосипед, а теперь вы пытаетесь превратить COW-велосипед в «std::string с COW». Как так получилось?
COW-велосипед не должно интересовать то, какая там реализация должна быть в стандарте. Особенно в контексте того, что у COW совершенно другая терминология и семантика.
В вашем примере нет никакого деления, нет никакой векторизации. Вам об этом сообщили — вы всё перепутали. Вам нужно это осознать и сделать соответствующие выводы.
Ваш пример — это 1в1 то, что критиковал автор, а именно — кэширование 1/n, а после использование этого коэффициента для замены деления на умножения. При его вычисление НЕ ИСПОЛЬЗУЕТ НИКАКИХ " выполнять на лету при помощи векторных инструкций. ", вообще никаких векторных инструкций.
Никакого отношения ваш пример к векторизации деления не имеет. Повторюсь уже в 3-4раз.
Это ни из чего не следует. По крайней мере я не вижу связи, но вы можете мне её показать. Внимательно слушаю.
Тут и не нужны никакие кишки. Вызов clone/copy не является кишками. Шарить «cow-копии» строки между тредами нельзя, так же как и ссылки, так же как и мувить из другого треда и прочее.
На любое чтение — процессор прочитает кешлайн. Если этот кешлайн далее не нужен — он вытеснится чтением другого кешлайна. И это, ровным счётом, ни на что не повлияет.
Это абсолютно неважно. Число может быть каким угодно — определяющим является их кол-во, а не то «большое» оно, либо нет.
Неверно. Можно хранить целые вектора, либо есть броадкаст. Да что там далеко ходить — по вашей ссылки есть пример:
__m128 _k = _mm_set1_ps(1.0f / p);
Это именно одно число с «броадкастом», ничего не мешает подставить сюда число из таблицы.
Никаких проблем нет, если нам нужно и умножать на последовательность чисел — она спокойно читается.
Таблица таблице рознь, но до — таблица не векторизуется и они почти полностью бесполезны при векторизации.
Этот пример никакого отношения к тому, о чём вы говорите — не имеет. Это оптимизация деления на констанату, которая вычисляется не «при помощи векторных инструкций», а банальным делением, а потом используется как константа при вычислениях.
Если у вас константа одна и её можно предрассчитать, то проще предрассчитать, но не всегда и не везде. К тому же — есть множество кейсов, где длинна предвычисление будет стоит дорого, неоправданно дорого.
В данном примере просто векторизуется операция int(float(d)/float(p))*p. Причём очень колхозно. И самое интересное — этот же пример вас опровергает. Это деление будет исполнятся значительную часть от самого цикла. 10-20+% и это лишь потому, что флоат-деление достаточно халявное. К тому же флоаты тут явно не подходят, ведь их точности на инт не хватит — нужны даблы. Там уже ситуация будет куда хуже.
К тому же, не стоит забывать, что данная реализация слишком кастыльная — там почти всё время тратится на касты. Будь это изначально флоаты/даблы — мы бы потеряли не 10-20%+, а все 100%+.
И нам бы пришлось выносить это из цикла, т.е. кэшировать вычисление.