TGTGInsightintelligence telegramLIVE / telegram public index
Torna ai canali
Experimental chill avatar

TGINSIGHT CHAT

Experimental chill

@experimentalchill

Tecnologie

Algorithms, libraries, C++, Linux, Distributed Systems, maybe Rust Donate: https://t.me/experimentalchill/222 Author: @Danlark Nothing in this blog is an opinion of my employer

Iscritti9,320Iscritti attuali
Post tracciati120Post indicizzati
Reach recente215,200Visualizzazioni post recenti
Post recenti

Post recenti

Pag. 3 di 10 · 120 post

Pubblicato 10 gen

Недавно понадобилось снова открыть документацию и посмотреть что значат регистры %fs и %gs: я помню что-то про thread local storage, но не более. Наткнулся на очень красивый ответ об истории https://stackoverflow.com/questions/10810203/what-is-the-fs-gs-register-intended-for/10810340 The original intention behind the segment registers was to allow a program to access many different (large) segments of memory that were intended to be independent and part of a persistent virtual store. The idea was taken from the 1966 Multics operating system, that treated files as simply addressable memory segments. No BS "Open file, write record, close file", just "Store this value into that virtual data segment" with dirty page flushing. ... There was still a need for threads to access thread local store, and each thread needed a a pointer ... somewhere in the immediately accessible thread state (e.g, in the registers) ... to thread local store. Since Windows and Linux both used FS and GS (thanks Nick for the clarification) for this purpose in the 32 bit version, AMD decided to let the 64 bit segment registers (GS and FS) be used essentially only for this purpose (I think you can make them point anywhere in your process space; I don't know if the application code can load them or not). Intel in their panic to not lose market share to AMD on 64 bits, and Andy being retired, decided to just copy AMD's scheme.

16,100 views

Pubblicato 21 dic

В C++20 завезли destroying delete operator. Его основное отличие от обычного delete -- что при удалении через destroying delete вы сначала заходите в функцию, где сами должны вызвать деструктор struct Foo { ~Foo() { std::cout << "In Bar::~Bar()\n"; } void operator delete(Foo* p, std::destroying_delete_t) { std::cout << "In Foo::operator delete(Foo*, std::destroying_delete_t)\n"; p->~Foo(); ::operator delete(p); } }; https://gcc.godbolt.org/z/zqd8Yn7ff Из интересного, вы теперь можете сами писать свои vtable: https://gcc.godbolt.org/z/EYMn1sd1o struct Vehicle { const enum Types { CAR, TRUCK } type; Vehicle(Types t) : type(t) {} void operator delete(Vehicle*, std::destroying_delete_t); }; // Implement Car, Truck void Vehicle::operator delete(Vehicle *p, std::destroying_delete_t) { switch (p->type) { case CAR: static_cast<Car*>(p)->~Car(); break; case TRUCK: static_cast<Truck*>(p)->~Truck(); break; } ::operator delete(p); } Когда вы можете писать свои vtable, вы можете классы инициализировать через memset и тд, потому что вы убираете полную инициализацию. Например, протобуфы. Все они наследуются от MessageLite, а теперь в кодогенерации можносвою vtable написать и инициализировать все поля быстро через mem*. До этого это было undefined behavior из-за нефиксированности имплементации vtable. https://en.cppreference.com/w/cpp/memory/new/operator_delete. Cм 27-30.

17,700 views

Pubblicato 17 dic

Тут выложили видео со мной на CppCon https://www.youtube.com/watch?v=cMRyQkrjEeI Вроде даже неплохо получилось. Конец года наступает, а посты всё реже и реже выходят. Я очень много занимался тем, о чём вообще нельзя рассказывать, какие-то внутренние штуки, о которых невозможно писать, не рассказав тучу контекста. Технологический мир в последний год был сфокусирован вокруг LLM, а мне посредственно интересна эта тема. Можно поговорить про UltraFastBERT https://arxiv.org/pdf/2311.10770.pdf , где используют часть нейронов через дерево и с помощью sparse matrix multiplication достигают 78x быстрее inference, но, к сожалению, только на CPU. В целом потолок виден в уменьшении всего этого, но алгоритм не положить на GPU и это вопрос на следующий миллиард долларов. Удешевить всё дело в 80 раз даст доступ к LLM всем в каждом углу. Я вообще редко читаю на постоянной основе чужие блоги, но блог Стивена Вольфрама мне особенно понравился в прошлом году. Например, про ChatGPT. The basic answer, I think, is that language is at a fundamental level somehow simpler than it seems. And this means that ChatGPT is successfully able to “capture the essence” of human language and the thinking behind it. And moreover, in its training, ChatGPT has somehow “implicitly discovered” whatever regularities in language (and thinking) make this possible. ... And perhaps there’s nothing to be said about how it can be done beyond “somehow it happens when you have 175 billion neural net weights”. But I strongly suspect that there’s a much simpler and stronger story. В целом проекты как https://github.com/tinygrad/tinygrad могут попытаться сделать что-то около крутого вокруг идеи much simpler and stronger story. Пытаться утилизировать всё, в т. ч. на CPU имеет смысл и здравый риск. George Hotz, несмотря на всю его спорную личность, очень сильный инженер и, наверное, много в моем стиле программирования я взял от него. В универе смотрел его стримы чуть ли не 24/7 на старших курсах. Ещё из интересного я вошёл в комитет по разработке следующего поколения SIMD на Arm -- может быть назовём SVE 3 или как-то так. Учитывая, что SVE2 и SVE2.1 было фактически задизайнено Apple и не особо развивалось у них за ненадобностью, то может быть получится продвинуть дело подальше в правильном направлении.

47,400 views

Pubblicato 21 nov

2311.09394.pdf

16,400 views

Pubblicato 21 nov

Тут вышла статья от Кости Серебряного -- человек, который себе карьеру сделал на ASAN, Fuzzing и тд про GWP-ASAN. Это своеобразная модификация аллокатора, которая не включает полную мощь ASAN в проде, так как будут проблемы с оверхедом, а создаёт отдельный буффер, где страницы памяти Linux чередуются -- то, из чего можно читать и то из чего нельзя (PROT_NONE), таким образом легче словить out of bounds ошибки. При аллокациях выдаётся память из одного региона, где можно читать, при деаллокации тоже помечается PROT_NONE, а при use after free, если повезёт, и попадёт туда, куда не надо, то найдёт ошибку в C/C++ подобном коде. Тем самым случайным образом аллокации попадают в буффер и имеют шансы обнаружить ошибки уже не в тестах, а в проде. Ну, мы знаем такие техники, и вероятности не очень большие поймать при одном запуске. Прелесть такого метода в том, что оверхед минимальный, меньше 0.2% А теперь предположим у вас есть софт, который распространяется на тысячи, миллионы людей и девайсов. Google, Apple, Meta, приложения в Google/App Store, софт Windows, игра в Steam или просто серверы и их много, и работают они долго. Так получается, что вы теперь проверяете на корректность не какой-то участок кода при запуске, а размазываете ASAN на все аллокации на тысячах и миллионах устройств. Сотни, тысячи багов, простая имплементация и красивая история. Ни тесты, ни фаззинг не спасают от багов в проде

17,300 views

Pubblicato 20 nov

Тут была конференция SOSP . Запомнились некоторые интересные статьи Silent Data Corruption in Alibaba Cloud. По сравнению со статьями от Google и Meta, Alibaba раскрыла больше данных о том насколько часто находятся битые процессоры и данные в проде. Из интересного, они увидели, что если процессор сильнее нагревается, то вероятность битой инструкции экспоненциально увеличивается. Из ещё забавного -- битфлипы очень часто происходят на тех же позициях в регистре при попытках воспроизвести. Из странного, большинство багов не находят в preprod. Из не понравившегося -- много странных графиков, экстраполяция по 27 битым процессорам и тд. Project Silica: Towards Sustainable Cloud Archival Storage in Glass. Это, наверное, самая интересная статья, которую я прочитал. Суть в том, что хранение очень холодных данных на магнитных технологиях вроде HDD и тд дорогое, надо обновлять, так как диски вылетают и не остаются на десятки лет. Авторы рассказывают о 12-летнем опыте, как можно хранить данные в стекле, которое не ржавеет и не гниет, у которого срок службы >1k лет. Да, в стекле прям вырезают биты и в итоге данные хранятся дольше. QuePaxa: Escaping the Tyranny of Timeouts in Consensus. В консенсусных алгоритмах вроде Raft и Paxos часто таймауты вызывают переизбрание лидера. При всяких DoS аттаках система встаёт и не очень продвигается. В итоге поставишь большой таймаут -- долго будет переизбрание, маленький -- слишком много. В QuePaxa предлагают делать хеджирование запросов, чтобы проверять liveness, модификацию Paxos, чтобы несколько proposers предлагали себя с весами в зависимости от быстроты ответов. Интересная и технически непростая статья. A Cloud-Scale Characterization of Remote Procedure Calls. Статья от Google про 700 миллиардов RPC внутри нас, что мы выучили и куда стремимся с точки зрения оверхеда и Software. Смотрим на библиотеки, scheduling, cross DC traffic. Показываем,что в DC мы всё ещё millisecond-scale и до micro-second нам ещё далеко. Много времени в статье уделяется tail latency -- сколько занимает оверхед RPC framework на 99%. Один из авторов Soheil -- невероятно приятный человек, с кем работать одно удовольствие. Статья читается просто и даёт много инсайтов, что происходит внутри с сетью с точки зрения пользователя.

14,400 views

Pubblicato 6 nov

Давно я не писал, поэтому чуть больше в одном посте 1. Я тут сегодня нашёл интересное применение алгоритма поиска максимального потока, о котором вы вряд ли слышали -- для тестов. В GUnit есть функция UnorderedElementsAre(container), которая сравнивает, что два множества совпадают. Проблема в том, что для общего случая элементы могут быть несравнимы или нехешируемы, тогда проверять на равенство становится сложнее, так как запрещены сортировки и хеш-мапы. Задача решается с помощью максимального паросочетания: между двумя множествами строится граф равенства и после этого находится максимальное паросочетание. В GUnit код находится здесь. UPD. Также в комментариях подсказали, что такая абстракция удобна для того, чтобы иметь разные проверки, скажем, что в множестве есть элементы строго больше, чем в другом (пример). 2. В Google обновился C++ Style Guide на C++20. Ничего не написано про модули, ranges и корутины, потому что всё ещё нет консенсуса. В целом хорошее изменение, вещи прогрессируют. 3. Тут рассказано, сколько фаззеру надо было фаззить, чтобы найти известный сверху баг в WebRTC: https://www.srlabs.de/blog-post/advanced-fuzzing-unmasks-elusive-vulnerabilities . TL;DR 20 независимых байт, что достаточно много для фаззеров. В похожем баге в ZSTD, который мы нашли в марте, надо было около 7-8 специфичных байт после того как фаззер зашёл в нужную строчку кода. Чтобы найти баг в ZSTD и WebRTC нужны более интересные техники. Например, в ZSTD хватило бы добавлять 2^n рандомных байт в конец, а в WebRTC сделать большой if/switch на табличку в 256 байт. Кажется нужен стажёр 4. Google Pixel 8 имеет поддержку Arm MTE. Это фича, которая помечает аллокации специальными тегами на уровне битов указателей и проверяет на уровне железа, читаете ли вы валидную память. Надеюсь, мы найдем очень много всякого разного со временем. 5. Я выложил свою презентацию с CppCon про сортировки https://danlark1.github.io/cppcon_sort_2023 . Запись будет где-то в январе :)

13,500 views

Pubblicato 17 ott

Contest Пописал тут контест от телеграма https://t.me/contest/330. В целом задача -- всё, что написано в markup code в телеге -- определить, код ли это и какого языка программирования из 100 самых популярных. Как обычно, ни данных, ни условий тестирования не дали, классический телеграм. Из уже существующий решений есть * VSCode'овский https://github.com/yoeo/guesslang, прилагающий к нему https://github.com/yoeo/guesslangtools. Из хорошего, 55 языков поддерживает c 90%+ качеством, из плохого работает на больших кусках кода. * Какая-то статья https://github.com/aliostad/deep-learning-lang-detection, утверждают 99%+ качества. Обучение у них на слишком хороших данных. * Какие-то регексовские вещи, которые очевидно никогда не наберут 90%+ качества Вторую я покрутил, повертел и получил тоже ~90% качества на средненьких таких данных. Как брать данные * https://libraries.io/ * https://huggingface.co/datasets/bigcode/the-stack * https://sourcegraph.com/search -> Actions -> Export Results В эпоху LLM, на hugging face собрали неплохой датасет, который я почему-то нашёл только в последние пару дней, чутка оттуда покачал, но особо много это не дало, а кластера для терабайтов у меня не было. В итоге использовал libraries.io и sourcegraph. Собрал я 5M файлов, качал я это дело на 5TB машинке пару дней, github отдавал разным машинам в районе 50-100MB/s в зависимости проснулись ли прогеры из Сан Франциско :), много тротлили, но я их переиграл. Суммарно после дедупликации получилось 100GB кода. Дальше начинается самое веселое. Из хорошего в файлах гитхаба есть расширение, которое почти однозначно определяет язык. Ага, конечно, .hh -> C++ и Hack .p -> Gnuplot и OpenEdgeABL .fs -> Forth и F# У гитхаба есть неплохой алгоритм детекции таких disputes: heuristics.yml на регулярных выражениях. Целый день я сидел и фильтровал данные, помимо добавлял языки программирования, которых Github не знает. Например, FunC и FIFT. В целом видна человеческая рука здесь по добавлению 2 языков программирования от уважаемого Николая. По всему интернету файлов существует в районе 1000 и спасибо sourcegraph, который смог это всё найти. Но мусора в расширениях .fc и .fift было предостаточно, выфильтровали :) Далее обучение. Я взял guesslang и чутка крутил batchsize, hidden dnn layers и получил в среднем 88% аккуратности и 92.5% на топ50 самых популярных языках В конце начинается самое интересное, а собственно, как достать markup comments телеграма? К сожалению, датасетов почти нет, tgstat.ru не сохраняет информацию об этом. Я покачал каких-то прогерских community и докручивал на маленьких данных. Самое плохое, что лучше всего сработало при маленьких кусках кода просто повторить его, пока не станет 30-40 строк кода. От таких положений вещей модель начинала сходиться к правильным ответам чаще. Ещё, конечно, не забывайте, что любой текст это Markdown, поэтому чтобы различить одно от другого надо постараться. Докручивали уже disputes какими-то регекспами из heuristics.yml и логикой, мол, если строк мало, то вряд ли это эзотерический язык. Всё равно люди компилируют C код как C++, а Hack почти в природе нет, кроме как у Meta. Самое сложное в конце было найти баланс, а что в общем-то авторы, хотят, что они вообще будут тестировать и какое распределение у всего и вся. Скорее всего будет 95% не языков программирования. Последние полдня потратил на то, чтобы собрать tensorflow C++ с нуля и вкомпилить в .so, потому что принимать ничего другого они не хотят. Ну что ж, значит tensorflow. Скомпилировал. Отправил 600Mb .so файл. Зато более менее работает, 2-3 ms на 4kb. Делал я это дело 7-8 дней, из которых 3 полных часов по 10, ещё часа по 3-4 вечерами в оставшиеся дни. Что будет, то будет. Ради фана и узнать что-то новое делал. Узнал о многих языках программирования вроде Raku, ICON, Keyman, LOGO. И получайте почти красивую картинку confusion matrix.

15,900 views

Pubblicato 17 ott

11,000 views

Pubblicato 4 ott

Тут вышла OOPSLA -- хорошая конференция по языкам программирования. Зацепило 3 статьи Randomized Testing of Byzantine Fault Tolerant Algorithms https://dl.acm.org/doi/10.1145/3586053 Блокчейн всё таки принёс пользу -- теперь у нас есть какое-то количество византийских протоколов (то есть распределённых протоколов, которые сохраняют свойства, но могут портить сообщения и тд), и рисёрчеры подтянулись и придумали интересное тестирование -- давайте тестировать не только случайные падения и случайные изменения, а опишем структурно как в фаззинге что можно менять. Из неочевидных свойств -- пишут, что именно сок в мелких изменениях, так обнаружилось больше багов. ByzzFuzz detected several bugs in the implementation of PBFT, a potential liveness violation in Tendermint, and materialized two theoretically described vulnerabilities in Ripple’s XRP Ledger Consensus Algorithm. Moreover, we discovered a previously unknown fault-tolerance bug in the production implementation of Ripple, which is confirmed by the developers and fixed. Fat Pointers for Temporal Memory Safety of C https://dl.acm.org/doi/10.1145/3586038 Давным давно уже пытаются создать язык Checked-C, который проверяет, всё ли хорошо с разыменовываниями указателей. Только Checked-C работает только с массивами, мол, не выходите за границы. А вот сохранения протухших указателей намного сложнее найти -- надо уже смотреть за лайфтаймами. Статья придумала жирные указатели, которые аннотируются метаданными, куда ушёл указатель и будет ли он изменён потом. Лёгкое дополнение к трансформации компиляции. 2/3 статьи о том, как это сделать быстро с ассемблером и тд. Пишут о 1-2k строк в день миграции. На самом деле вывод более интересный -- если тесты неплохие, то в целом вы получите код с unique ownership, а значит его и легче будет переписать/протранслировать на Rust уже какой-нибудь автоматической тулзой. То есть не сразу писать C -> Rust, а C -> Checked-C -> Rust, что будет менее болезненно и потенциально последняя часть автоматически. Accelerating Fuzzing through Prefix-Guided Execution https://dl.acm.org/doi/10.1145/3586027 Одна из проблем фаззинга, как было видно в прошлых постах, скорость с которой он сходится для багов. Иногда не находит годами. Если его ускорить раза в два, может быть будут шансы найти что-то побыстрее. В статье рассказывают как фаззинг устроен в целом, мол, если вход не увеличил покрытие, то он выбрасывается. Авторы увидели интересную особенность, что покрытие улучшается практически всегда, когда тест доходит до определенного префикса выполнения -- то есть если код веток на 20, то достаточно часто посмотреть на первые 5 и если мы пришли в те же 5 веток, то можно просто не исполнять вход дальше. Особенность интересная, но весьма теоретическая -- это число "5" для всех разное и найти его -- надо потратить какое-то время на нахождение его бинарным поиском. Но абсолютно магическим фактом кажется, что это число почему-то существует на всём, на чём потестили и достигает того же покрытия, что и обычный фаззер за 3-10x меньше времени. Прямо применить будет слегка сложно, но рисёрч продолжается. Вообще Zhendong Su -- какая-то звезда современного рисёрча фаззинга, у него по несколько статей в год.

15,600 views

Pubblicato 23 set

Фаззили 5 лет и не нашли Читал тут как в дереве хаффмана нашли out of bounds read в libwebp https://blog.isosceles.com/the-webp-0day/. Есть спекуляции, что этим пользуется Pegasus. И снова вопрос, почему фаззинг не нашёл такой пример за 5 лет фаззинга? Не похоже ли это на https://t.me/experimentalchill/238, когда мы в ZSTD нашли битые данные хотя фаззили достаточно несложный код 2 года? Как я уже писал, в фаззинге нет магии, он просто пытается зайти во все строки кода, и совсем странные крайние случаи вряд ли найдёт. Всем советую прочитать анализ, а так если кто-то хочет написать сложный проект по тому, как находить такие баги чаще, то welcome. Это в самом деле a million dollar question, без преувеличения.

14,800 views

Pubblicato 15 set

Resources BurntSushi обновил ripgrep для Arm пользуясь моими советами и статьёй, что не может не радовать, теперь с его слов "In short, simple ripgrep searches (likely the most common kind) get about twice as fast on Apple silicon now." Unrelated. Одна из больших ошибок в науке перформанса, на которую я обращал не так много внимания в первые годы, хотя стоило бы -- утилизация. Я очень люблю разворачивать циклы, улучшать алгоритмы и тд, но микробенчмарки врут, они однопоточные часто, и они часто всю память кладут в L1/L2 кеш и получается очень красиво, мол, вот вам, соптимизировали. Сейчас я даже не говорю про промахи мимо кешей, а именно как хорошо вы можете утилизировать все ресурсы. Memory bandwidth между памятью и ядрами сейчас упирается в 30-100 GB/s и не растёт. После этого порога -- тьма. Это означает, что в целом бесполезно оптимизировать хоть что угодно -- вы упёрлись в память. На одном процессе с десяток потоков не так страшно, но когда вы пытаетесь загрузить машинку и каждый процесс кушает свои 5-10GB/s, то в целом вы никогда не увидите, что упираетесь в CPU. И опять же, бесполезно оптимизировать хоть что-то на микробенчмарках, вы упираетесь в потолок, потому что просто хотите прочитать или записать память. Какие ошибки и эффекты у этого всего? 1. "Ух, сейчас распараллелим на 32 потока и заживём". Нет, упрётесь в потолок и будете как на однопоточном. 2. "Что-то на одной машинке 99th latency совершенно другая, хотя вроде железо одно и то же". Да, потому что соседи могут всё скушать, а вам не особо что останется. 3. "Сэкономили 10% CPU, сейчас закажем машинок поменьше". Увы, не всегда 4. "Давайте кешик побольше сделаем и заживём". Опять же, шаг влево и бекенды будут отвечать в разы хуже На практике пока не всё так плохо, но процессоры всё ещё развиваются, а скорость передачи данных всё, у неё истек закон Мура. 3-5% в год? Что делать? Уменьшайте работу с памятью. Трогайте горячие данные чаще, холодные реже. Собирайте кеш промахи (LLC-load-misses в perf stat) профайлом и уменьшайте их (хотя это может помочь *соседу* на машине, а не вам). Меньше алгоритмов на табличках, больше на CPU, меньше данных в целом. Удаляйте данные, перекладывайте меньше jsonов в конце концов, а.

15,100 views