Pull to refresh
0
0
Send message
Помимо рассмотренных вами приложений, работающих с небольшими наборами данных, есть приложения, где узкое место — память, и активный датасет занимает несколько мегабайт.

Смысл в том, что реальность она сложнее. В ней нет такого понятия как «узкое место — память» — у памяти есть совершенно разные места, которые могут быть узкими.

Как мы уже выяснили — есть две основные метрики — летенси и трупут. Причём они не определяются примитивными определениями уровня «последовательное — трупут, а рандомное — летенси», как многие делают. Это фундаментальное-противоположные вещи, с совершенно разными свойствами.

Всё это можно определить через уровень параллельности конкретной задачи. И в зависимости от этого уровня — всё может очень сильно меняться. Допустим, как я уже говорил, вычисления — это, в основном, хорошо распараллеливаемые задачи( не нужно ограничивать параллельность потоками ОС). Это задачи упирающиеся в трупут — нет смысла приводить какие-то цифры, которые никакого отношения к данному кейсу не имеют.

Кейсы с хорошим уровнем параллелизма могут быть и 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тактов — это трупут( и тут даже написано это).

Инструмент не принимает во внимание летенси кешей, мало того, что это полная ахинея, дак к тому же ещё куда-то потерялось летенси дива. Куда? Ведь его летенси инструмент так же не принимает во внимание?

А что же у нас там по трупуту кешей?
L2 Write (Write, 64 bytes step) = 6.1 cycles per write (cache line)
L3 Write (Write, 64 bytes step) = 8.4 cycles per write (cache line)

Ой, опять у нас какие-то проблемы. Почему же? Может потому, что не нужно писать рандомные фразы в ответ?

В любом случае — я уже всё сказал. Хотите играть в эту клоунаду — играйте. Впаривать наивным людям, с умным видом, ахинею — хорошее занятие, удобное занятие. Особенно на те темы, в которых мало кто разбирается. Продолжайте.

Данный вывод сходится с выводом из статьи «Станет ли быстрее с таким кешированием единиц или нет — непонятно:<и далее по тексту> может стать лучше<...>может ухудшиться». (Я вообще удивлён, что вы пытаетесь спорить с таким выводом!).

Подобные выводы не имеют смысла. И опять же, глупая попытка врать. Куда вы потеряли все остальные тезисы? Про «тратить 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. Тут можно пытаться ехать в сторону «а как нам пошарить две одинаковые строки между тредами», но это так же не является проблемой. Решается одним методом, который делает реальную копию.

Information

Rating
Does not participate
Registered
Activity