Pull to refresh
28
0
Send message

Глупые фокусы: преобразование 32-битного значения в 64-битное, когда неважен мусор в старших битах

Level of difficultyMedium
Reading time4 min
Views2.9K

Предположим — у вас имеется функция, которая передаёт 32-битное значение другой функции, принимающей 64-битные значения. Вам совершенно неважно то, что попадёт в 32 старших бита, так как это значение функция, принимающая его, напрямую не обрабатывает. Его просто передают функции обратного вызова, которая обрезает его, преобразуя в 32-битное значение. При этом, по некоей причине, вас беспокоит влияние на производительность той единственной инструкции, которую компилятор обычно генерирует для расширения 32-битных значений до 64-битных.

Первое, что я по этому поводу подумал, выглядело так: «Да зачем об этом беспокоиться, если пока ничего особенного не произошло». Подозреваю, что одна единственная инструкция не превратится в узкое место некоей программы.

Но, несмотря на это, я, просто из интереса, решил попробовать решить эту хитрую задачку.

Я решил использовать встроенный ассемблер gcc/clang и написать код, который сообщает системе: «Я могу создать 64-битное значение из 32-битного, не выполнив ни одной инструкции».

Читать далее

Современный C++23/26: концепты, корутины и многое другое в высокопроизводительных службах

Level of difficultyMedium
Reading time11 min
Views8.9K

C++ уже десятки лет является краеугольным камнем, на котором строятся программы, ориентированные на высокую производительность. Он лежит в основе самых разных проектов, относящихся практически ко всем аспектам человеческой деятельности — от встроенных систем до платформ высокочастотной торговли. Его возможности по совмещению низкоуровневых средств управления вычислительными ресурсами с высокоуровневыми абстракциями превращают его в уникальный инструмент, подходящий для создания программ, при выполнении которых значение имеет каждая микросекунда. По мере того, как язык развивается, новые стандарты, вроде C++23 и ожидаемого C++26, вводят в него функционал, который улучшает и его возможности по созданию высокопроизводительных программ, и продуктивность пользующихся им программистов. Особенно это касается разработки высокопроизводительных служб — систем, которым требуются низкие задержки и высокие значения пропускной способности, которые нуждаются в эффективном использовании ресурсов. Среди них — аналитические системы, работающие в режиме реального времени, игровые серверы и распределённые системы управления базами данных.

Читать далее

Оптимизация производительности кода — это тяжёлый труд

Level of difficultyMedium
Reading time10 min
Views3.8K

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

Статья, которую вы читаете — это, отчасти, рассуждения о том, сколько огорчений мне приносит оптимизация кода. Но я, кроме того, попытаюсь дать здесь практические советы, которые, надеюсь скрасят путь тем, кто идёт дорогами оптимизации.

Читать далее

Опыт PostHog: 50 советов о создании успешных продуктов

Level of difficultyEasy
Reading time12 min
Views2.3K

Для того чтобы отпраздновать то, что рассылка Product for Engineers набрала 50000 подписчиков, мы решили поделиться пятьюдесятью советами, в которых собрано всё самое важное, что мы узнали о разработке успешных программных продуктов.

Читать далее

С++ — это настоящий кайфǃ

Level of difficultyEasy
Reading time18 min
Views49K

Я хочу, чтобы вы задали себе один вопрос и честно на него ответили. Когда в последний раз вы получали настоящее удовольствие от программирования? Оглядываясь назад, я понимаю, что не испытывал подобных ощущений, наверное… уже лет десять. Удовольствия у меня не было ни от JavaScript, ни от Python, ни от Ruby или C — ни от чего. Когда я говорю «удовольствие» — я имею в виду ощущения человека, которого во время работы над неким проектом переполняет искренний восторг. Этот человек постоянно ловит себя на такой мысли: «Ох, ну какая ж круть. Поверить не могу, что моя безумная идея и правда сработала!».

Например, я писал маленькую игру-«рогалик». У меня была такая идея: «Готов поспорить, что у меня получиться воспользоваться этим вашим алгоритмом Дейкстры для соединения комнат при генерировании карты, сначала инвертируя карту, а потом его запуская. Вероятно, мне удастся прокопать отличнейшие туннели между комнатами». То было благословенное время, когда я пытался справиться с этой задачей, и при этом не чувствовал, что C++ мне мешает. Мне тогда удалось решить эту задачу, попутно многому научившись. Потом у меня появилась такая мысль: «Интересно, получится мне взять пользовательский интерфейс, сделанный на FTXUI, и просто напрямую его отрендерить в окно визуализации SFML?». Как и следовало ожидать, у меня всё отлично получилось. И хотя это было не так уж и сложно, я по ходу дела много узнал о том, как в C++ обрабатывается юникод. Ни одна из этих задач лёгкой не была, но все их, в принципе, можно было решить, и я не могу напридумывать себе достаточно много «подводных камней», которыми C++ мог бы помешать мне сделать то, что я хочу. Это — то, что я называю «удовольствием».

Читать далее

Эксперименты с фиксированной статистической мощностью: вопрос не в подглядывании, а в том, на что именно смотрят

Reading time14 min
Views1.7K

Иногда до начала эксперимента не удаётся оценить то, какого размера должна быть выборка, способная обеспечить его нормальное проведение. Для решения этой проблемы можно провести последовательный тест или A/A‑тест. Но последовательные тесты обычно отличаются меньшей чувствительностью и оказывают отклоняющее влияние на статистическую оценку эффекта воздействия. A/A‑тесты увеличивают длительность экспериментов, не гарантируя при этом того, что найденный в итоге размер выборки окажется корректным. В этом материале мы представим основные моменты из нашей недавней публикации (Precision‑based designs for sequential randomized experiments, Mattias Nordin, Mårten Schultzberg, 2024), в которой мы представляем альтернативный метод, названный нами «fixed‑power design» (схема эксперимента с фиксированной статистической мощностью). При применении схем с фиксированной статистической мощностью эксперимент начинают, не имея оценки размера выборки. Необходимый размер выборки находят, опираясь на имеющиеся данные о текущих результатах эксперимента. Эксперимент останавливают в тот момент, когда текущий размер выборки оказывается больше необходимого размера выборки. Мы покажем, что эксперименты с фиксированной статистической мощностью можно анализировать, используя стандартные методы без какой‑либо коррекции. Точечные оценки оказываются непротиворечивыми, а доверительные интервалы эффекта воздействия обладают асимптотическим номинальным покрытием. Не все формы «подглядывания» приводят к увеличению частоты появления ложноположительных выводов на основе выборки фиксированного размера.

Читать далее

Никакого праздника без GPU: дообучение BERT на Vertex AI

Level of difficultyMedium
Reading time17 min
Views3K

Этот материал посвящён ускорению обучения моделей с использованием бессерверных заданий. В частности, речь пойдёт о том, как запускать обучение с применением Pytorch, GPU и платформы Vertex.

Читать далее

Обратный поиск по федеративному графу Netflix

Level of difficultyMedium
Reading time10 min
Views1.2K

В Netflix было сделано много нового со времён выхода предыдущих материалов, посвящённых роли тех, кто отвечает за направление Content Engineering, в реализации поиска по нашему федеративному графу (federated graph). А именно, в первой статье мы идентифицировали проблему и рассказали об использовании инфраструктуры индексирования данных, а во второй мы углубились в вопрос о том, как мы пользуемся очередями. Мы дали доступ к Studio Search для всех инженеров компании, а не только для тех, кто занимается направлением Content Engineering, и переименовали этот проект в Graph Search. С Graph Search интегрировано более 100 приложений. В рамках этой системы поддерживается примерно 50 индексов. Мы продолжаем расширять её функционал. Как было обещано в предыдущем материале, здесь мы расскажем о том, как мы, объединив усилия с одной из команд, отвечающих за Studio Engineering, создавали обратный поиск (reverse search). Обратный поиск переворачивает с ног на голову стандартный подход к выполнению запросов: вместо того, чтобы искать документы, которые соответствуют запросу, он направлен на поиск запросов, соответствующих документу.

Читать далее

Толстые хвосты распределений — это загадочно и странно

Level of difficultyMedium
Reading time13 min
Views9.3K

Если вы посещали занятия по статистике — вы, возможно, проходили тему «общая теория меры». Там могла идти речь о мере и об интеграле Лебега, а так же — об их связи с другими способами интегрирования. Если на ваших занятиях много внимания уделялось математике (так было у меня), то на них вы вполне могли познакомиться с теоремой Каратеодори о продолжении меры и даже с основами теории операторов на гильбертовых пространствах, а так же — с преобразованиями Фурье и много с чем ещё. Большинство этих математических конструкций нацелено на доказательство одной из самых важных теорем, на которой основана огромная часть статистики. Речь идёт о центральной предельной теореме (ЦПТ).

ЦПТ утверждает, что для широкого класса того, что мы называем в математике «случайными величинами» (которые представляют собой результаты проведения некоего эксперимента, включающего в себя элемент случайности), до тех пор, пока они удовлетворяют определённым условиям (как может показаться — простым), их среднее значение сходится к случайной величине определённого типа, который называют «нормальным» или «Гауссовым».

Читать далее

О создании системы, преобразующей текст в SQL для аналитиков Pinterest

Reading time10 min
Views4.8K

Написание запросов для решения аналитических задач — это основное занятие тех, кто работает с данными Pinterest. Но подбор подходящих данных и преобразование описания проблемы в корректный и эффективный SQL‑код могут оказаться непростыми делами. Ведь речь идёт о среде, которая быстро меняется, и о значительных объёмах данных, разбросанных по разным местам.

Читать далее

Как Notion проектировал свой data lake, чтобы успевать за быстрым ростом

Level of difficultyMedium
Reading time16 min
Views9.1K

За последние три года размер данных Notion увеличился в 10 раз из‑за роста количества пользователей и объёмов контента, с которым они работают. Удвоение этого показателя происходило каждые 6–12 месяцев. Нам нужно было справиться со стремительным ростом размеров данных, соответствуя при этом постоянно растущим требованиям, которые выдвигали критически важные сценарии использования наших продуктов и аналитических систем. Особенно это справедливо в применении к новым функциям Notion AI. Для того чтобы решить эти задачи нам нужно было создать озеро данных Notion и обеспечить его масштабирование. Вот как мы это сделали.

Читать далее

Всё, что вам нужно — это линейное внимание

Level of difficultyHard
Reading time9 min
Views11K

Можно ли реализовать механизм внутреннего внимания, потребляющий гораздо меньше ресурсов, чем обычно?

Говорят, что механизм внимания плохо переносит работу с последовательностями большой длины. Это — идея, которая встречалась любому, кто потратил достаточно много времени, занимаясь трансформерами и механизмом внутреннего внимания. Это, одновременно, и так, и не так. С одной стороны — с этим сталкивался каждый, кто пытался увеличить размеры контекста своей модели, натыкаясь при этом на то, что модель начинала работать с сильным скрипом. С другой стороны — возникает такое ощущение, что практически каждую неделю выходит новая эталонная модель, которая характеризуется новыми размерами контекста, бьющими все рекорды. (Контекстное окно Gemini составляет 2 миллиона токенов!)

Есть много хитроумных методов, вроде RingAttention, которые позволяют обучать модели с очень большими размерами контекста на мощных распределённых системах. Но сегодня меня интересует всего один простой вопрос: «Как далеко можно зайти, применяя лишь механизм линейного внимания?».

Читать далее

История терминала как инструмент продуктивности

Level of difficultyEasy
Reading time7 min
Views9K

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

Читать далее

Реальность обладает поразительным числом деталей

Level of difficultyEasy
Reading time12 min
Views16K

Мой отец эмигрировал из Колумбии в Северную Америку, когда ему было 18. Сделал он это в поисках лучшей жизни. Для меня и моего брата это значило — проводить много времени на уличном холоде. Отец выбрал путь улучшения своей судьбы через улучшение того, что его окружает. Меня и брата «добровольно» завербовали в помощники по работам над принадлежащими нам постройками.

Именно так значительную часть подростковых лет я провёл, чиня изгороди, роя ямы, строя перекрытия и навесы. И если я чему и научился, занимаясь всеми этими строительными делами, так это тому, что реальность обладает удивительным количеством деталей.

Читать далее

Трансформеры, группы преобразований и self-attention

Level of difficultyHard
Reading time10 min
Views5.1K

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

Читать далее

Организация ML-монорепозитория с помощью Pants

Level of difficultyMedium
Reading time24 min
Views2.3K

Приходилось вам копипастить фрагменты вспомогательного кода между проектами, попадая в ситуацию, когда несколько версий одного и того же набора команд оказывались в разных репозиториях? Или, может, вам надо было делать pull‑запросы к десяткам проектов после того, как было изменено имя GCP‑корзины, где вы храните данные?

Подобные ситуации возникают в ML‑командах слишком часто. Тяжесть их последствий варьируется от мелких неудобств для отдельного разработчика до нарушения работы целой команды, которая оказывается не в состоянии вовремя выдать код, над которым трудится. К счастью, эти проблемы поддаются исправлению.

Предлагаю погрузиться в тему монорепозиториев. Это — архитектура, широко применяемая в ведущих технологических компаниях наподобие Google. Поговорим о том, как монорепозитории способны улучшить ваши рабочие процессы, связанные с машинным обучением. Монорепозитории дают тем, кто их выбирает, много полезного. Это, несмотря на то, что есть у них и недостатки, делает их привлекательным выбором для управления сложными ML‑экосистемами.

Сначала мы кратко обсудим сильные и слабые стороны монорепозиториев, поговорим о том, почему они — это отличное архитектурное решение для ML‑команд, коснёмся того, как их используют в крупных технологических компаниях. В итоге у нас появится представление о том, как воспользоваться возможностями системы сборки кода Pants для организации ML‑репозиториев при построении надёжной CI/CD‑системы для сборки проектов.

А теперь — в путь — к оптимизации управления проектами в сфере машинного обучения.

Читать далее

Как я за один заход хакнул половину американских сетей фастфуда

Reading time3 min
Views34K

Консоль бодро оповестила меня о завершении работы скрипта. Его задача заключалась в поиске учётных данных для доступа к Firebase, которые лежали в открытом доступе и принадлежали одному из сотен недавно появившихся ИИ‑стартапов.

Скрипт шёл по общедоступному списку сайтов с использованием домена верхнего уровня .ai. Программа парсила данные сайтов (и любые.js‑бандлы, на которые находила ссылки) в поиске переменных, которые обычно используются для настройки подключения к Firebase.

Читать далее

Аннотирование args и kwargs в Python

Level of difficultyEasy
Reading time4 min
Views14K

Когда я пытаюсь обойтись без *args и **kwargs в сигнатурах функций, это не всегда можно сделать, не вредя удобству использования API. Особенно — когда надо писать функции, которые обращаются к вспомогательным функциям с одинаковыми сигнатурами.

Типизация *args и **kwargs всегда меня расстраивала, так как их нельзя было заблаговременно снабдить точными аннотациями. Например, если и позиционные, и именованные аргументы функции могут содержать лишь значения одинаковых типов, можно было поступить так:

def foo(*args: int, **kwargs: bool) -> None:
    ...

Применение такой конструкции указывает на то, что args — это кортеж, все элементы которого являются целыми числами, а kwargs — это словарь, ключи которого являются строками, а значения имеют логический тип.

Но нельзя было адекватно аннотировать *args и **kwargs в ситуации, когда значения, которые можно передавать в качестве позиционных и именованных аргументов, могут, в разных обстоятельствах, относиться к различным типам. В таких случаях приходилось прибегать к Any, что противоречило цели типизации аргументов функции.

Читать далее

Добавление собственных данных в LLM с помощью RAG

Level of difficultyMedium
Reading time28 min
Views48K

Этот материал посвящён тому, как добавлять собственные данные в предварительно обученные LLM (Large Language Model, большая языковая модель) с применением подхода, основанного на промптах, который называется RAG (Retrieval‑Augmented Generation, генерация ответа с использованием результатов поиска).

Большие языковые модели знают о мире многое, но не всё. Так как обучение таких моделей занимает много времени, данные, использованные в последнем сеансе их обучения, могут оказаться достаточно старыми. И хотя LLM знакомы с общеизвестными фактами, сведения о которых имеются в интернете, они ничего не знают о ваших собственных данных. А это — часто именно те данные, которые нужны в вашем приложении, основанном на технологиях искусственного интеллекта. Поэтому неудивительно то, что уже довольно давно и учёные, и разработчики ИИ‑систем уделяют серьёзное внимание вопросу расширения LLM новыми данными.

До наступления эры LLM модели часто дополняли новыми данными, просто проводя их дообучение. Но теперь, когда используемые модели стали гораздо масштабнее, когда обучать их стали на гораздо больших объёмах данных, дообучение моделей подходит лишь для совсем немногих сценариев их использования. Дообучение особенно хорошо подходит для тех случаев, когда нужно сделать так, чтобы модель взаимодействовала бы с пользователем, используя стиль и тональность высказываний, отличающиеся от изначальных. Один из отличных примеров успешного применения дообучения — это когда компания OpenAI доработала свои старые модели GPT-3.5, превратив их в модели GPT-3.5-turbo (ChatGPT). Первая группа моделей была нацелена на завершение предложений, а вторая — на общение с пользователем в чате. Если модели, завершающей предложения, передавали промпт наподобие «Можешь рассказать мне о палатках для холодной погоды», она могла выдать ответ, расширяющий этот промпт: «и о любом другом походном снаряжении для холодной погоды?». А модель, ориентированная на общение в чате, отреагировала бы на подобный промпт чем‑то вроде такого ответа: «Конечно! Они придуманы так, чтобы выдерживать низкие температуры, сильный ветер и снег благодаря…». В данном случае цель компании OpenAI была не в том, чтобы расширить информацию, доступную модели, а в том, чтобы изменить способ её общения с пользователями. В таких случаях дообучение способно буквально творить чудеса!

Читать далее

16-, 8- и 4-битные форматы чисел с плавающей запятой

Level of difficultyMedium
Reading time15 min
Views33K

Уже лет 50, со времён выхода первого издания «Языка программирования Си» Кернигана и Ритчи, известно, что «числа с плавающей запятой» одинарной точности имеют размер 32 бита, а числа двойной точности — 64 бита. Существуют ещё и 80-битные числа расширенной точности типа «long double». Эти типы данных покрывали почти все нужды обработки вещественных чисел. Но в последние несколько лет, с наступлением эпохи больших нейросетевых моделей, у разработчиков появилась потребность в типах данных, которые не «больше», а «меньше» существующих, потребность в том, чтобы как можно сильнее «сжать» типы данных, представляющие числа с плавающей запятой.

Я, честно говоря, был удивлён, когда узнал о существовании 4-битного формата для представления чисел с плавающей запятой. Да как такое вообще возможно? Лучший способ узнать об этом — самостоятельно поработать с такими числами. Сейчас мы исследуем самые популярные форматы чисел с плавающей запятой, создадим с использованием некоторых из них простую нейронную сеть и понаблюдаем за тем, как она работает.

Читать далее
1
23 ...

Information

Rating
Does not participate
Works in
Registered
Activity