Видно вы не поняли, что я имею ввиду под синхронизацией для асинхронности. Это память, неважно где, в которой записано, что нужно пнуть подзадачу с такой-то точки исполнения при опр. условиях. Если не сохранить точку синхронизации исполнения, то асинхронность невозможна, т.к. невозможно продолжить прерванное исполнение подзадачи. Если такой синхронизации нет, то подзадача не асинхронна.
Много вопросов к сваливанию в кучу доп. абстракций разных уровней. Есть ли планировщик задач, как он работает, что есть потоки для планировщика, что есть задачи для планировщика, что за ядра процессора, какое исполнение на ядрах процессора, бесконечное и т.д. и т.п.?
Вот пишу unikernel и организовать исполнение задач можно синхронно/параллельно/асинхронно. Можно отключить прерывания (точки синхронизации для асинхронщины) и асинхронность становится простой абстракцией без ног. Если отключить доп. ядра, то параллельность уже не добавишь никак. Если отключить и последнее ядро, то и задачки уже не порешать никак. Отсюда приходит мысль, что синхронные вычисления первичны, параллельность синхронных вторична, а асинхронность на самом деле простая абстракция без ног, которой нет разницы на чьей шее сидеть.
Асинхронность предполагает точку синхронизации (когда можно продолжить исполнение след. куска подзадачи - пресловутые await), если нет синхронизации, то её нет. Разрыв исполнения подзадачи должен быть, чтобы назвать её асинхронной. Параллельность - про исполнение подзадач одновременно. Без синхронизации в ней не будет асинхронности, т.к. не будет логического разрыва исполнения.
Т.е. 128b/130b, 64b/66b, 8b/10b кодирование это враньё? Я думал о чём-то таком (8b/6t) https://en.wikipedia.org/wiki/4B3T Лучше от 128b/Nt, чтобы было ближе к макс. плотности. Если там плотнее кодируется нормально, то неплохо, но тройка всё равно должна давать максимум плотности при 3, 9, 27 и т.д. уровнях на такт.
Edit: Хотя по энергоэффективности выгоднее пару линий с PAM-3 и (M)b/(N)t кодировкой, т.к. 9 уровней это слишком жёстко.
У Ethernet протокола на 1Гбит там 1.25+Гбит на физ. уровне. И такие люди будут думать о выгоде в 1.5+ раза по плотности информации для передачи? Бред же. Потом добавьте потери скорости при перекодировании из двоичной в троичную и обратно. Ещё меньше людей будет о таком думать. Элементная база нужна + толстый заказчик, т.к. на малых объёмах экономика не экономит. Круг заинтересованных людей сужается в точку.
Если бы все думали, что все за них уже всё подумали, то сидели бы мы в какой-нибудь пещере нынешней Франции. Если у вас есть мат./физ. док-ва, что это невозможно, то кидайтесь ссылками, чтобы и меня просветить.
Тройка оптимальна для многих реальных задач (те же задачки с гирями), т.к. теоретически получается макс. плотность информации на единицу трёхстабильного элемента.
Минус только в сложности переключения в трёхстабильных элементах (либо энергопотребление большое, либо переключение долгое, либо другие минусы). Хотя патенты только в путь клепают по ним, но из них не очень ясно приемлемы ли они для реального применения или просто кто-то вышел покурить-подумать и придумал фигню.
Для передачи большого кол-ва информации лучше использовать троичную систему (напр. на оптоволокне и спец. лазерах), т.к. 661578 разряд в троичной хранит больше информации чем 1048576 разрядов в двоичной и нужно передавать сигнал в ~1.584962 (для 64 байтов [мин. ethernet пакет] - 512 бит, что меньше информации в 324 тритах, кол-во необходимых сигналов для передачи сокращается в ~1.580247 раз) раза меньшее кол-во раз - время передачи сокращается, расход энергии сокращается. Больше информации за раз - больше экономия. Напр., для видео/аудио и пр. больших объёмов, для небольших - лучше двоичными, т.к. там разница в ~1.5 раза и выгода от использования пары трёхстабильных элементов для передачи троичных данных стремится к 0.
Т.е. и троичный процессор должен работать с блоками, а не с отдельными тритами (SIMD), чтобы выгода была отлична от 0 по объёму схемотехники и энергопотреблению. Т.е. не для обычных пользователей, т.к. кач-во кода в таких системах не впечатляет (от ОС и до пользовательских программ).
"VLESS Reality сигнатуры не имеет" - как бы статистический анализ должен работать вне зависимости от транспорта (статистическая сигнатура сильно отличается от нормы, в чёрный список, а IP ограничены). Запихали медиа в трубу и на другом конце не белосписочное хранилище медиа? Выглядит подозрительно, Чебурнет такого не допустит. А сайтики смотреть - проблем не должно быть больших, если не слишком много и часто (тоже подозрительно и сайты не помогают - постоянно шлют дичь и с нескольких источников канал будет толще нормы всегда). Белосписочные реле, но им тоже всё это видно. Любой предопределённый поток имеет сигнатуру. Всё равно, что всё зашифровано известным ключём. И подражать потоком одной плотности потоку с меньшей плотностью - удачи, расскажите потом сколько кбит/с у вас на источник данных в итоге выходит.
Любой контакт, что вы не инициировали - скорее всего развод (начальник/родственник/скамер/и т.д. нашёл лоха для своих целей). В телеге постоянно пишут (в качестве развлечения можно пописать в ответ с помощью чат гопоты какой-нибудь, но быстро надоедает).
Схема простая - перегрузить мозг данными и пока он пытается вытянуть из них информацию отдавать команды почти без обработки мозгом. DoS + усиливающаяся из-за этого уязвимость в виде непрямого управления. А если там DDoS по нескольким каналам, то ещё хуже (эмоциональных людей лучше изолировать от себя при любых серьёзных контактах, т.к. они будут мощной доп. нагрузкой из-за которой вас могут развести как лоха).
Т.е. защититься от этого сложно (сам когда-то давно попался на развод, хоть и контакт инициировал сам и там схема с подменой целевого контакта была, но мозг так работает, что можно им управлять извне в опр. условиях), если команды в мозг отправляют довольно простые по нагрузке (мозг любит экономить на вычислениях): кликни здесь, напечатай под диктовку / по буквам (если нужно самому где-то вычитать и печатать [много], то уже мозг получит время подумать "а нафига? нормально же было, ничего не делал, что тут началось?") и т.п. простые операции. Но современные сервисы даже в критических местах спроектированы под простоту и скам процветает. Но это нужно через регуляторов продавливать, чтобы на автопилоте нельзя было работать с критичными данными/доступами.
Лучше на железку арбузы кидать, т.к. это материальное что-то, а не ссылка динамическая. Бороться с доменами довольно бесполезно (хотя РКН пытается, уровень компетенций печален).
256MiB (со всем, что я там наделал. с prefetcht0 на 0.2-0.35ms дольше исполняется чем с prefetchnta, а так стабильно предзагрузка лучше) AVX2 normal assembly sum: Sum=134216776.000; best time = 57.612553ms AVX2 prefetch assembly sum: Sum=134216776.000; best time = 56.600445ms
цикл развёрнут на все 16 регистров (предзагрузке чуть хуже становится, обычному варианту на % лучше): AVX2 normal assembly sum: Sum=134225120.000; best time = 57.081848ms AVX2 prefetch assembly sum: Sum=134225120.000; best time = 56.624981ms
Рандом (одинаково или так): Random load NO prefetch : 216 cycles Random load WITH prefetch: 180 cycles Improvement: +16.67 %
Тогда `prefetchnta` (и положить в регистр) и просто не мусорить в кеш. Это намного быстрее, чем мусорить в кеш с помощью железки. Но также как и железка этот вариант будет добавлять DRAM refresh задержки в общую обработку случайным образом, т.к. окно (только понял, что это основное, что хотел донести изначально) предзагрузки слишком маленькое, чтобы оно не влияло на результат.
Предзагрузка - чтобы работать как конвеер из стиралок и сушилок, а не как стиралка-сушилка (железный вариант обязателен для старого софта, а так - часто мешает, вспомнить хотя бы мусорные кеш линии для ограждения данных потоков). Задача - скрыть время доступа к внешней памяти.
Сомневаюсь, что железный предзагрузчик может скрыть почти 1us DRAM refresh (некоторые работы в этой области намекают, что точно не может и все решения memory bound задач просто живут с этими непредсказуемыми задержками), т.к. типичный доступ к памяти не занимает много сотен наносекунд. Если взять доступ L1d за 4-5 циклов, то на 5GHz ядре один DRAM refresh это провал по времени почти в 1000000 кеш линий (почти 64KiB, если обработка <1 цикла на кеш линию), а т.к. там нужна синхронизация на это время все полученные параллельно из памяти кеш линии для ядра будут ждать "неудачную" (попала в банку с DRAM refresh) предзагрузку кеш линии. И если нет предзагруженного буфера почти в 64KiB хотя бы в L3 работа будет просто останавливаться на сотни наносекунд.
Будем мы их сразу использовать или нет не имеет значения. Там LRU, поэтому при нагрузке на кеш предзагрузка теряет свою эффективность настолько, что предзагружать много кеш линий задолго до их обработки становится вредно (т.к. железная предзагрузка ещё добавит нагрузки на кеш).
Запрет вытеснения это хорошо, но что-то всё равно будет вытеснено, а магия это плохо.
А дальше на скорости памяти. L3 и L2 предзагрузку заранее никто не отменял по аналогичным приципам, поэтому там скорее на пару MiB хватит сразу, а потом смешанная предзагрузка блоков кеш линий по мере исчерпания текущих. Если надеятся на железо, то можно поймать DRAM refresh прям во время обработки и почти 1us куковать периодически.
Если можно гарантировать невытеснение кеш линий, то программно можно предзагрузить хоть половину L1d. Зная кол-во параллельных предзагрузок можно начередовать их с другими инструкциями оптимальным образом (ещё нужно помнить про выравнивание инструкций и пр. специфику, о которой я скорее всего ещё не знаю...).
При наличии других прожорливых потоков смысл от программной предзагрузки теряется, т.е. предзагружать много линий не имеет смысла, т.к. вероятность их вытеснения до использования сильно возрастает.
Для bare metal под одну задачу такой проблемы нет и программная предзагрузка/освобождение блоков памяти надёжнее и выгоднее (известно когда и сколько предзагружать, когда и сколько освобождать - т.е. не нужно заниматься предсказаниями и лишними оптимистичными инструкциями) надежды на железо.
Возможно нужно clflushopt всех кеш линий массива сделать перед каждым прогоном (пока не знаю, как в расте это правильно сделать). Ещё есть вопросы к среде исполнения т.к. разница в 1мс вне зависимости от подхода выглядит очень странно. Возможно нужно проводить бенч на bare metal, чтобы исключить постороннее влияние.
Поменял местами бенчи, увеличил размер массива до 16MiB, поменял код в перфетче на (смешанный prefetch кеш линий начала след. двух циклов [там 2-3 порта для загрузки ymm, поэтому после каждых двух загрузок из памяти поставил prefetch]): "2:",
// ---- PREFETCH 2 iterations ahead (256 bytes) ----
// ---- Main loads ----
"vaddps ymm0, ymm0, [rdi + r10*4]",
"vaddps ymm1, ymm1, [rdi + r10*4 + 32]",
"prefetcht0 [rdi + r10*4 + 128]",
"vaddps ymm2, ymm2, [rdi + r10*4 + 64]",
"vaddps ymm3, ymm3, [rdi + r10*4 + 96]",
"prefetcht0 [rdi + r10*4 + 256]",
и получаю такое: AVX2 prefetch assembly sum: Sum=8387048.000; best time = 3.43813ms
AVX2 normal assembly sum: Sum=8387048.000; best time = 4.428003ms AVX2 prefetch assembly sum: Sum=8388720.000; best time = 3.4316ms
AVX2 normal assembly sum: Sum=8388720.000; best time = 3.44306ms AVX2 prefetch assembly sum: Sum=8389057.000; best time = 3.506484ms
AVX2 normal assembly sum: Sum=8389057.000; best time = 3.44506ms AVX2 prefetch assembly sum: Sum=8388825.000; best time = 3.545974ms
AVX2 normal assembly sum: Sum=8388825.000; best time = 4.455999ms
при смене порядка бенчей к оригинальному, но со всеми изменениями выше: AVX2 normal assembly sum: Sum=8388928.000; best time = 3.761652ms
AVX2 prefetch assembly sum: Sum=8388928.000; best time = 3.715009ms AVX2 normal assembly sum: Sum=8389341.000; best time = 3.425933ms
AVX2 prefetch assembly sum: Sum=8389341.000; best time = 3.466136ms AVX2 normal assembly sum: Sum=8390126.000; best time = 3.712881ms
AVX2 prefetch assembly sum: Sum=8390126.000; best time = 3.749143ms AVX2 normal assembly sum: Sum=8389072.000; best time = 4.363928ms
AVX2 prefetch assembly sum: Sum=8389072.000; best time = 4.551079ms AVX2 normal assembly sum: Sum=8387146.000; best time = 4.432056ms
AVX2 prefetch assembly sum: Sum=8387146.000; best time = 3.523452ms AVX2 normal assembly sum: Sum=8388622.000; best time = 3.360004ms
AVX2 prefetch assembly sum: Sum=8388622.000; best time = 4.496095ms
ещё лучше можно сделать так (можно до 8+ [нужно смотреть по процу, сколько у него их] линий держать некешируемых), т.к. мы только читаем (проблема с доп. задержкой в 1мс остаётся, но происходит гораздо реже для prefetchnta варианта): "2:",
// ---- PREFETCH 2 iterations ahead (256 bytes) ----
// ---- Main loads ----
"vaddps ymm0, ymm0, [rdi + r10*4]",
"vaddps ymm1, ymm1, [rdi + r10*4 + 32]",
"prefetchnta [rdi + r10*4 + 128]",
"prefetchnta [rdi + r10*4 + 256]",
"vaddps ymm2, ymm2, [rdi + r10*4 + 64]",
"vaddps ymm3, ymm3, [rdi + r10*4 + 96]",
"prefetchnta [rdi + r10*4 + 192]",
"prefetchnta [rdi + r10*4 + 320]",
AVX2 normal assembly sum: Sum=8388643.000; best time = 3.431242ms
AVX2 prefetch assembly sum: Sum=8388643.000; best time = 3.271411ms
Там же у SIMD инструкций load сильно ограничен (меньше 4 одновременно, т.е. простой большой, если нет доп. операций для исполнения пока оно там крутится) по кол-ву одновременных. Максимум можно предварительно в L1d подгрузить, если оно ещё не там. Из L1 грузить будет вроде бы 4-5 циклов. Потом fused load+add. А т.к. там больше ничего не происходит одновременно (хотя бы тот же prefetch - т.к. цикл не очень предсказуемая вещь и можно начать тянуть память для след. итерации цикла в L1), то просто простой конвеера скорее всего происходит пока load порты заняты.
В итоге не транспорт, а какая-то дичь. ipv6 в это дно ещё глубже закопался: трусы, крест и погремушка бонусом. Потому его везде отключаю, т.к. первый принцип оптимизации - просто не делать бесполезную работу (может я ошибаюсь и ipv6 это не бесполезная работа, но его необходимость пока под вопросом, т.к. утилизация даже публичных ipv4 небольшая [блоки они навыделяли, но без использования это просто бесполезная работа, т.е. вся система выделения IP адресов довольно бесполезна для решения основной задачи, это не считая большие блоки адресов, что они там зарезервировали под всякую дичь]). Печально, что всё так и будет гнить в этом направлении.
Если нужно можно было сделать за столько лет. Но там про распил бюджета с имитацией бурной деятельности (как и везде). Большая часть anti-DPI решений обрубается лёгким движением руки, но сломаются странные впны и пр. странные сетевые телодвижения (включая некоторые методы в основе DoS атак). Даже вшивые сайты прикручивают морды от ботов и пр., а здесь они не могут общую локалку запилить с простой контролируемой адресацией, чтобы любой трансграничный запрос определялся провайдером по одному байту и уходил в чёрные ящики на фильтрацию. Ничего сложного нет. Это база любой нормальной системы. С какими там она "специалистами" общалась - непонятно. Есть другие способы решения, но запилить общую локалку проще и дешевле всего.
Вообще к основным протоколам интернета много вопросов, могли бы заодно для локалки нормальные протоколы разработать, чтобы убожество в виде IP + TCP/UDP с их убогими портами и пр. ненужной ересью умерло хотя бы в этой локалке.
Если писать софт (CUDA) для неизвестно кого, получается неизвестно что. Если писать софт под одну задачу, то можно много чего на одном месте вертеть. От стандартов до лучших практик и пр.
Видно вы не поняли, что я имею ввиду под синхронизацией для асинхронности. Это память, неважно где, в которой записано, что нужно пнуть подзадачу с такой-то точки исполнения при опр. условиях. Если не сохранить точку синхронизации исполнения, то асинхронность невозможна, т.к. невозможно продолжить прерванное исполнение подзадачи. Если такой синхронизации нет, то подзадача не асинхронна.
Много вопросов к сваливанию в кучу доп. абстракций разных уровней. Есть ли планировщик задач, как он работает, что есть потоки для планировщика, что есть задачи для планировщика, что за ядра процессора, какое исполнение на ядрах процессора, бесконечное и т.д. и т.п.?
Вот пишу unikernel и организовать исполнение задач можно синхронно/параллельно/асинхронно. Можно отключить прерывания (точки синхронизации для асинхронщины) и асинхронность становится простой абстракцией без ног. Если отключить доп. ядра, то параллельность уже не добавишь никак. Если отключить и последнее ядро, то и задачки уже не порешать никак. Отсюда приходит мысль, что синхронные вычисления первичны, параллельность синхронных вторична, а асинхронность на самом деле простая абстракция без ног, которой нет разницы на чьей шее сидеть.
Асинхронность предполагает точку синхронизации (когда можно продолжить исполнение след. куска подзадачи - пресловутые await), если нет синхронизации, то её нет. Разрыв исполнения подзадачи должен быть, чтобы назвать её асинхронной. Параллельность - про исполнение подзадач одновременно. Без синхронизации в ней не будет асинхронности, т.к. не будет логического разрыва исполнения.
Т.е. 128b/130b, 64b/66b, 8b/10b кодирование это враньё?
Я думал о чём-то таком (8b/6t) https://en.wikipedia.org/wiki/4B3T
Лучше от 128b/Nt, чтобы было ближе к макс. плотности.
Если там плотнее кодируется нормально, то неплохо, но тройка всё равно должна давать максимум плотности при 3, 9, 27 и т.д. уровнях на такт.
Edit: Хотя по энергоэффективности выгоднее пару линий с PAM-3 и (M)b/(N)t кодировкой, т.к. 9 уровней это слишком жёстко.
У Ethernet протокола на 1Гбит там 1.25+Гбит на физ. уровне. И такие люди будут думать о выгоде в 1.5+ раза по плотности информации для передачи? Бред же.
Потом добавьте потери скорости при перекодировании из двоичной в троичную и обратно. Ещё меньше людей будет о таком думать.
Элементная база нужна + толстый заказчик, т.к. на малых объёмах экономика не экономит. Круг заинтересованных людей сужается в точку.
Если бы все думали, что все за них уже всё подумали, то сидели бы мы в какой-нибудь пещере нынешней Франции. Если у вас есть мат./физ. док-ва, что это невозможно, то кидайтесь ссылками, чтобы и меня просветить.
Тройка оптимальна для многих реальных задач (те же задачки с гирями), т.к. теоретически получается макс. плотность информации на единицу трёхстабильного элемента.
Минус только в сложности переключения в трёхстабильных элементах (либо энергопотребление большое, либо переключение долгое, либо другие минусы). Хотя патенты только в путь клепают по ним, но из них не очень ясно приемлемы ли они для реального применения или просто кто-то вышел покурить-подумать и придумал фигню.
Для передачи большого кол-ва информации лучше использовать троичную систему (напр. на оптоволокне и спец. лазерах), т.к. 661578 разряд в троичной хранит больше информации чем 1048576 разрядов в двоичной и нужно передавать сигнал в ~1.584962 (для 64 байтов [мин. ethernet пакет] - 512 бит, что меньше информации в 324 тритах, кол-во необходимых сигналов для передачи сокращается в ~1.580247 раз) раза меньшее кол-во раз - время передачи сокращается, расход энергии сокращается. Больше информации за раз - больше экономия. Напр., для видео/аудио и пр. больших объёмов, для небольших - лучше двоичными, т.к. там разница в ~1.5 раза и выгода от использования пары трёхстабильных элементов для передачи троичных данных стремится к 0.
Т.е. и троичный процессор должен работать с блоками, а не с отдельными тритами (SIMD), чтобы выгода была отлична от 0 по объёму схемотехники и энергопотреблению. Т.е. не для обычных пользователей, т.к. кач-во кода в таких системах не впечатляет (от ОС и до пользовательских программ).
"VLESS Reality сигнатуры не имеет" - как бы статистический анализ должен работать вне зависимости от транспорта (статистическая сигнатура сильно отличается от нормы, в чёрный список, а IP ограничены). Запихали медиа в трубу и на другом конце не белосписочное хранилище медиа? Выглядит подозрительно, Чебурнет такого не допустит. А сайтики смотреть - проблем не должно быть больших, если не слишком много и часто (тоже подозрительно и сайты не помогают - постоянно шлют дичь и с нескольких источников канал будет толще нормы всегда). Белосписочные реле, но им тоже всё это видно.
Любой предопределённый поток имеет сигнатуру. Всё равно, что всё зашифровано известным ключём. И подражать потоком одной плотности потоку с меньшей плотностью - удачи, расскажите потом сколько кбит/с у вас на источник данных в итоге выходит.
Любой контакт, что вы не инициировали - скорее всего развод (начальник/родственник/скамер/и т.д. нашёл лоха для своих целей). В телеге постоянно пишут (в качестве развлечения можно пописать в ответ с помощью чат гопоты какой-нибудь, но быстро надоедает).
Схема простая - перегрузить мозг данными и пока он пытается вытянуть из них информацию отдавать команды почти без обработки мозгом. DoS + усиливающаяся из-за этого уязвимость в виде непрямого управления. А если там DDoS по нескольким каналам, то ещё хуже (эмоциональных людей лучше изолировать от себя при любых серьёзных контактах, т.к. они будут мощной доп. нагрузкой из-за которой вас могут развести как лоха).
Т.е. защититься от этого сложно (сам когда-то давно попался на развод, хоть и контакт инициировал сам и там схема с подменой целевого контакта была, но мозг так работает, что можно им управлять извне в опр. условиях), если команды в мозг отправляют довольно простые по нагрузке (мозг любит экономить на вычислениях): кликни здесь, напечатай под диктовку / по буквам (если нужно самому где-то вычитать и печатать [много], то уже мозг получит время подумать "а нафига? нормально же было, ничего не делал, что тут началось?") и т.п. простые операции. Но современные сервисы даже в критических местах спроектированы под простоту и скам процветает. Но это нужно через регуляторов продавливать, чтобы на автопилоте нельзя было работать с критичными данными/доступами.
Лучше на железку арбузы кидать, т.к. это материальное что-то, а не ссылка динамическая. Бороться с доменами довольно бесполезно (хотя РКН пытается, уровень компетенций печален).
7 1800X (старый обычный Zen).
256MiB (со всем, что я там наделал. с prefetcht0 на 0.2-0.35ms дольше исполняется чем с prefetchnta, а так стабильно предзагрузка лучше)
AVX2 normal assembly sum: Sum=134216776.000; best time = 57.612553ms
AVX2 prefetch assembly sum: Sum=134216776.000; best time = 56.600445ms
цикл развёрнут на все 16 регистров (предзагрузке чуть хуже становится, обычному варианту на % лучше):
AVX2 normal assembly sum: Sum=134225120.000; best time = 57.081848ms
AVX2 prefetch assembly sum: Sum=134225120.000; best time = 56.624981ms
Рандом (одинаково или так):
Random load NO prefetch : 216 cycles
Random load WITH prefetch: 180 cycles
Improvement: +16.67 %
Тогда `prefetchnta` (и положить в регистр) и просто не мусорить в кеш. Это намного быстрее, чем мусорить в кеш с помощью железки.
Но также как и железка этот вариант будет добавлять DRAM refresh задержки в общую обработку случайным образом, т.к. окно (только понял, что это основное, что хотел донести изначально) предзагрузки слишком маленькое, чтобы оно не влияло на результат.
Предзагрузка - чтобы работать как конвеер из стиралок и сушилок, а не как стиралка-сушилка (железный вариант обязателен для старого софта, а так - часто мешает, вспомнить хотя бы мусорные кеш линии для ограждения данных потоков). Задача - скрыть время доступа к внешней памяти.
Сомневаюсь, что железный предзагрузчик может скрыть почти 1us DRAM refresh (некоторые работы в этой области намекают, что точно не может и все решения memory bound задач просто живут с этими непредсказуемыми задержками), т.к. типичный доступ к памяти не занимает много сотен наносекунд. Если взять доступ L1d за 4-5 циклов, то на 5GHz ядре один DRAM refresh это провал по времени почти в 1000000 кеш линий (почти 64KiB, если обработка <1 цикла на кеш линию), а т.к. там нужна синхронизация на это время все полученные параллельно из памяти кеш линии для ядра будут ждать "неудачную" (попала в банку с DRAM refresh) предзагрузку кеш линии. И если нет предзагруженного буфера почти в 64KiB хотя бы в L3 работа будет просто останавливаться на сотни наносекунд.
Будем мы их сразу использовать или нет не имеет значения. Там LRU, поэтому при нагрузке на кеш предзагрузка теряет свою эффективность настолько, что предзагружать много кеш линий задолго до их обработки становится вредно (т.к. железная предзагрузка ещё добавит нагрузки на кеш).
Запрет вытеснения это хорошо, но что-то всё равно будет вытеснено, а магия это плохо.
А дальше на скорости памяти. L3 и L2 предзагрузку заранее никто не отменял по аналогичным приципам, поэтому там скорее на пару MiB хватит сразу, а потом смешанная предзагрузка блоков кеш линий по мере исчерпания текущих. Если надеятся на железо, то можно поймать DRAM refresh прям во время обработки и почти 1us куковать периодически.
Если можно гарантировать невытеснение кеш линий, то программно можно предзагрузить хоть половину L1d. Зная кол-во параллельных предзагрузок можно начередовать их с другими инструкциями оптимальным образом (ещё нужно помнить про выравнивание инструкций и пр. специфику, о которой я скорее всего ещё не знаю...).
При наличии других прожорливых потоков смысл от программной предзагрузки теряется, т.е. предзагружать много линий не имеет смысла, т.к. вероятность их вытеснения до использования сильно возрастает.
Для bare metal под одну задачу такой проблемы нет и программная предзагрузка/освобождение блоков памяти надёжнее и выгоднее (известно когда и сколько предзагружать, когда и сколько освобождать - т.е. не нужно заниматься предсказаниями и лишними оптимистичными инструкциями) надежды на железо.
Возможно нужно clflushopt всех кеш линий массива сделать перед каждым прогоном (пока не знаю, как в расте это правильно сделать). Ещё есть вопросы к среде исполнения т.к. разница в 1мс вне зависимости от подхода выглядит очень странно. Возможно нужно проводить бенч на bare metal, чтобы исключить постороннее влияние.
Поменял местами бенчи, увеличил размер массива до 16MiB, поменял код в перфетче на (смешанный prefetch кеш линий начала след. двух циклов [там 2-3 порта для загрузки ymm, поэтому после каждых двух загрузок из памяти поставил prefetch]):
"2:", // ---- PREFETCH 2 iterations ahead (256 bytes) ---- // ---- Main loads ---- "vaddps ymm0, ymm0, [rdi + r10*4]", "vaddps ymm1, ymm1, [rdi + r10*4 + 32]", "prefetcht0 [rdi + r10*4 + 128]", "vaddps ymm2, ymm2, [rdi + r10*4 + 64]", "vaddps ymm3, ymm3, [rdi + r10*4 + 96]", "prefetcht0 [rdi + r10*4 + 256]",и получаю такое:
AVX2 prefetch assembly sum: Sum=8387048.000; best time = 3.43813ms AVX2 normal assembly sum: Sum=8387048.000; best time = 4.428003msAVX2 prefetch assembly sum: Sum=8388720.000; best time = 3.4316ms AVX2 normal assembly sum: Sum=8388720.000; best time = 3.44306msAVX2 prefetch assembly sum: Sum=8389057.000; best time = 3.506484ms AVX2 normal assembly sum: Sum=8389057.000; best time = 3.44506msAVX2 prefetch assembly sum: Sum=8388825.000; best time = 3.545974ms AVX2 normal assembly sum: Sum=8388825.000; best time = 4.455999msпри смене порядка бенчей к оригинальному, но со всеми изменениями выше:
AVX2 normal assembly sum: Sum=8388928.000; best time = 3.761652ms AVX2 prefetch assembly sum: Sum=8388928.000; best time = 3.715009msAVX2 normal assembly sum: Sum=8389341.000; best time = 3.425933ms AVX2 prefetch assembly sum: Sum=8389341.000; best time = 3.466136msAVX2 normal assembly sum: Sum=8390126.000; best time = 3.712881ms AVX2 prefetch assembly sum: Sum=8390126.000; best time = 3.749143msAVX2 normal assembly sum: Sum=8389072.000; best time = 4.363928ms AVX2 prefetch assembly sum: Sum=8389072.000; best time = 4.551079msAVX2 normal assembly sum: Sum=8387146.000; best time = 4.432056ms AVX2 prefetch assembly sum: Sum=8387146.000; best time = 3.523452msAVX2 normal assembly sum: Sum=8388622.000; best time = 3.360004ms AVX2 prefetch assembly sum: Sum=8388622.000; best time = 4.496095msещё лучше можно сделать так (можно до 8+ [нужно смотреть по процу, сколько у него их] линий держать некешируемых), т.к. мы только читаем (проблема с доп. задержкой в 1мс остаётся, но происходит гораздо реже для prefetchnta варианта):
"2:", // ---- PREFETCH 2 iterations ahead (256 bytes) ---- // ---- Main loads ---- "vaddps ymm0, ymm0, [rdi + r10*4]", "vaddps ymm1, ymm1, [rdi + r10*4 + 32]", "prefetchnta [rdi + r10*4 + 128]", "prefetchnta [rdi + r10*4 + 256]", "vaddps ymm2, ymm2, [rdi + r10*4 + 64]", "vaddps ymm3, ymm3, [rdi + r10*4 + 96]", "prefetchnta [rdi + r10*4 + 192]", "prefetchnta [rdi + r10*4 + 320]",AVX2 normal assembly sum: Sum=8388643.000; best time = 3.431242ms AVX2 prefetch assembly sum: Sum=8388643.000; best time = 3.271411msТам же у SIMD инструкций load сильно ограничен (меньше 4 одновременно, т.е. простой большой, если нет доп. операций для исполнения пока оно там крутится) по кол-ву одновременных.
Максимум можно предварительно в L1d подгрузить, если оно ещё не там.
Из L1 грузить будет вроде бы 4-5 циклов. Потом fused load+add. А т.к. там больше ничего не происходит одновременно (хотя бы тот же prefetch - т.к. цикл не очень предсказуемая вещь и можно начать тянуть память для след. итерации цикла в L1), то просто простой конвеера скорее всего происходит пока load порты заняты.
В итоге не транспорт, а какая-то дичь. ipv6 в это дно ещё глубже закопался: трусы, крест и погремушка бонусом. Потому его везде отключаю, т.к. первый принцип оптимизации - просто не делать бесполезную работу (может я ошибаюсь и ipv6 это не бесполезная работа, но его необходимость пока под вопросом, т.к. утилизация даже публичных ipv4 небольшая [блоки они навыделяли, но без использования это просто бесполезная работа, т.е. вся система выделения IP адресов довольно бесполезна для решения основной задачи, это не считая большие блоки адресов, что они там зарезервировали под всякую дичь]).
Печально, что всё так и будет гнить в этом направлении.
Если нужно можно было сделать за столько лет. Но там про распил бюджета с имитацией бурной деятельности (как и везде).
Большая часть anti-DPI решений обрубается лёгким движением руки, но сломаются странные впны и пр. странные сетевые телодвижения (включая некоторые методы в основе DoS атак).
Даже вшивые сайты прикручивают морды от ботов и пр., а здесь они не могут общую локалку запилить с простой контролируемой адресацией, чтобы любой трансграничный запрос определялся провайдером по одному байту и уходил в чёрные ящики на фильтрацию. Ничего сложного нет. Это база любой нормальной системы.
С какими там она "специалистами" общалась - непонятно. Есть другие способы решения, но запилить общую локалку проще и дешевле всего.
Вообще к основным протоколам интернета много вопросов, могли бы заодно для локалки нормальные протоколы разработать, чтобы убожество в виде IP + TCP/UDP с их убогими портами и пр. ненужной ересью умерло хотя бы в этой локалке.
Если писать софт (CUDA) для неизвестно кого, получается неизвестно что.
Если писать софт под одну задачу, то можно много чего на одном месте вертеть. От стандартов до лучших практик и пр.
ВПН/Прокси тупые и прогоняют всё. Оно же не на жуков хитрых рассчитано, а на обычных пользователей, что сольют все IP адреса.
Мутных фирм полно