Пользователь
std::move vs. std::forward
Несмотря на то, что материалов на тему move-семантики и идеальной передачи в Интернете предостаточно, вопросов типа «что я должен здесь использовать: move или forward?» не становится меньше или мне просто «везет» на них. Поэтому и решено было написать эту статью. Предполагается, что читатель хотя бы немного знаком с rvalue-ссылками, move-семантикой и идеальной передачей.
Предельная скорость USB на STM32F103, чем она обусловлена?
Но я же крутой, у меня теперь есть USB-анализатор (его разработка была описана в блоке из нескольких предыдущих статей). Посмотрев логи, я понял, что похоже, знаю, почему скорость невозможно поднять, даже если STM32F103 обслуживает исключительно USB и ничего больше. Даже начал писать о результатах… Но потом решил, что кому-то это будет не интересно, а кто-то скажет, что и так это знал.
Но неожиданно, с тех пор мне по работе уже трижды приходилось пересказывать эти результаты то Заказчикам, то коллегам. Все они считали, что этот контроллер может больше. И мне приходилось вновь и вновь показывать физическую суть. Поэтому сделать документ было нужно хотя бы чтобы давать его прочесть тем, кто вновь будет говорить, что шина шустрая, контроллер быстрый… Ну, а если и делать документ, то почему бы не оформить его в виде статьи и не выложить на всеобщее обозрение?
Итак, давайте выясним, почему именно STM32F103C8T6 не может прокачать по шине USB данные на скорости 12 мегабит, заняв всю ширину предоставленного канала, и можно ли с этим что-то сделать.
Парсим протобаф на скорости больше 2 Гб/с.: как я научился любить хвостовую рекурсию в C
Отличную функцию недавно добавили в основную ветку компилятора Clang. С помощью атрибутов
[[clang::musttail]]
или __attribute__((musttail))
теперь можно получить гарантированные хвостовые (tail) вызовы в C, C++ и Objective-C.int g(int);
int f(int x) {
__attribute__((musttail)) return g(x);
}
(Онлайн-компилятор)
Приёмы неблокирующего программирования: введение в compare-and-swap
В первой части этого цикла статей мы рассмотрели теорию, стоящую за одновременным доступом в моделях памяти, а также применение этой теории к простым чтениям и записям в память. Правда, этих примитивов оказывается недостаточны для построения высокоуровневых механизмов синхронизации вроде спинлоков, мьютексов и условных переменных. Хоть и полные барьеры памяти позволяют синхронизировать потоки с помощью приёмов, рассмотренных в предыдущей части (алгоритм Деккера), современные процессоры позволяют получить нужный эффект проще, быстрее и гибче — да, всё сразу! — с помощью операций compare-and-swap.
Для программистов ядра Linux операция обмена compare-and-swap выглядит так:
T cmpxchg(T *ptr, T old, T new);
где T может быть либо числовым типом не больше указателя, либо указателем на что-нибудь. Так как в C нет обобщённых функций, то подобный полиморфизм реализуется макросами. cmpxchg() — это очень аккуратно реализованный макрос, который ведёт себя как функция (например, вычисляет аргументы только один раз). В Linux также есть макрос cmpxchg64(), который работает с 64-битными целыми числами и недоступен на 32-битных платформах.
cmpxchg() читает значение по указателю *ptr и, если оно равно old, то заменяет его на new. Иначе же после чтения ничего не происходит. Считанное значение возвращается как результат операции, независимо от того, произошла ли запись. И всё это выполняется атомарно: если другой поток одновременно с cmpxchg() записывает что-то по адресу *ptr, то cmpxchg() ничего не меняет. Либо old становится new, либо текущее значение остаётся нетронутым. Поэтому cmpxchg() называют атомарной операцией read-modify-write.
Полезные консольные Linux утилиты
В этой подборке представлены полезные малоизвестные консольные Linux утилиты. В списке не представлены Pentest утилиты, так как у них есть своя подборка.
Осторожно много скриншотов. Добавил до ката утилиту binenv.
binenv — cамая интересная утилита для установки новых популярных программ в linux, но которых нет в пакетном менеджере.
Программа для создания deb-пакетов
Обычно для создания deb-пакетов используются консольные утилиты, но также существуют программы и с графическим интерфейсом. Об одной из таких программ я хочу рассказать в этом посте.
Валидация UTF-8 меньше чем за одну инструкцию на байт
Даниэль Лемир – профессор Заочного квебекского университета (TÉLUQ), придумавший способ очень быстро парсить double – совместно с инженером Джоном Кайзером из Microsoft опубликовали ещё одну свою находку: валидатор UTF-8, обгоняющий библиотеку UTF-8 CPP (2006) в 48..77 раз, ДКА от Бьёрна Хёрманна (2009) – в 20..45 раз, и алгоритм Google Fuchsia (2020) – в 13..35 раз. Новость об этой публикации на хабре уже постили, но без технических подробностей; так что восполняем этот недочёт.
Лайфхак: как спарсить гигабайт double-ов в секунду
Как в коде на C++ прочитать значение double из строки?
std::stringstream in(mystring);
while(in >> x) {
sum += x;
}
На Intel Skylake с компилятором GCC 8.3, такой код парсит 50 МБ/с. Жёсткие диски запросто обеспечивают последовательное чтение со скоростью в несколько ГБ/с, так что вне всякого сомнения, нас ограничивает не скорость чтения с диска, а именно скорость парсинга. Как его ускорить?
Первое, что напрашивается – отказаться от удобств, предоставляемых потоками в C++, и вызывать strtod(3) напрямую:
do {
number = strtod(s, &end);
if(end == s) break;
sum += number;
s = end;
} while (s < theend);
Скорость вырастает до 90 МБ/с; профайлинг показывает, что при чтении из потока выполняется ~1600 инструкций на каждое читаемое число, при использовании strtod – ~1100 инструкций на число. Стандартные библиотеки Си и C++ можно оправдать требованиями универсальности и переносимости; но если ограничиться парсингом только double и только на x64, то можно написать намного более эффективный код: хватит 280 инструкций на число.
Как имитировать марсианский рассвет: обзор умных систем освещения Nanoleaf Shapes
Мечтаете украсить дом цветными огнями светодиодной подсветки, но не знаете, с чего начать? Что же, теперь у вас есть вариант: новая серия умных модульных систем освещения Nanoleaf Shapes. Она так называется, потому что все модули, или панели, имеют разную форму. А значит, с этой системой можно сделать куда больше, чем с ее предшественницами: Aurora (переименована в Light) и Canvas.
Рассказываем, в чем прелесть световых панелей новой серии Shapes.
Multithreading
Разработчики часто сталкиваются с необходимостью разработки многопоточных приложений, поэтому вопросы многопоточности требуют детального изучения. Давайте познакомимся с основными терминами, используемыми в источниках информации о многопоточности, рассмотрим задачи и проблемы многопоточности и изучим средства стандартной библиотеки C++, которые помогут создавать многопоточные приложения.
Часть 2. MPI — Учимся следить за процессами
В этой статье мы узнаем как можно управлять процессами, узнавать их идентификаторы, количество процессов запущенных в приложении и напишем простенькую программу которая на примере покажет работу всех этих процедур.
Приёмы неблокирующего программирования: полные барьеры памяти
В первых двух статьях цикла мы рассмотрели четыре способа упорядочить доступ к памяти: load-acquire и store-release операции в первой части, барьеры чтения и записи в память — во второй. Теперь пришла очередь познакомиться с полными барьерами памяти, их влиянием на производительность, и примерами использования полных барьеров в ядре Linux.
Рассмотренные ранее примитивы ограничивают возможный порядок исполнения операций с памятью четырьмя различными способами:
- Load-acquire операции выполняются перед последующими чтениями и записями.
- Store-release операции выполняются после предыдущих чтений и записей.
- Барьеры чтения разделяют предыдущие и последующие чтения из памяти.
- Барьеры записи разделяют предыдущие и последующие записи в память.
Внимательный читатель заметил, что одна из возможных комбинаций в этом списке отсутствует:
Чтение выполняется... | Запись выполняется... | |
… после чтения | smp_load_acquire(), smp_rmb() | smp_load_acquire(), smp_store_release() |
… после записи | ??? | smp_store_release(), smp_wmb() |
Составное устройство USB на STM32. Часть 4: Два-в-одном
В заключительной части публикации о составном устройстве USB я расскажу о том, как заставил заработать составное устройство USB, а также поделюсь некоторыми неочевидными нюансами этого процесса.
Работа составных частей устройства была описана во второй и третьей частях публикации.
Ответы на вопрос, зачем это всё было затеяно, даются в начале первой части и в конце четвёртой.
Вышли ожидаемые релизы от Google: Flutter 2 и язык Dart 2.12
Корпорация Google продолжает развивать свои продукты. Несколько дней назад была представлена новая версия построения интерфейса пользователя Flutter 2. Она, по словам разработчиков, стала универсальным фреймворком, который позволяет разрабатывать любые типы программ. Это могут быть приложения как для десктопов, так и web-сервисы.
Flutter в процессе эволюции стал неплохой альтернативой React Native. Его главное достоинство — возможность на основе одной кодовой базы создавать приложения для разных платформ, включая iOS, Android, Windows, macOS и Linux. Плюс можно разрабатывать и чисто браузерные приложения. И да, обновление до 2 версии не влияет на поддержку продуктов, написанных на Flutter 1. Они без дополнительного редактирования кода могут быть адаптированы для работы на рабочем столе и в Web.
Кунг-фу стиля Linux: разбираемся с последовательными портами
Умный print для C
Для тех кто пишет на С, возможно, будет интересно как мне удалось создать умную функцию print(), в которую можно кидать переменные любого типа — дженерик print.
АЦП преобразования в указанные моменты времени на STM32
В этом посте я расскажу, как мне удалось заставить STM32F4 измерять аналоговые сигналы в указанные моменты времени с помощью DMA не расходуя вычислительных ресурсов микроконтроллера.
Решение уравнения тетраэдра доказано спустя десятки лет после компьютерного поиска
Как четыре математика решили вопрос о базовых геометрических фигурах, создав полный список тетраэдров с рациональными углами при помощи методов теории чисел.
Все 59 тетраэдров с рациональными двугранными углами можно рассмотреть с разных сторон по ссылке.
Тетраэдр — это простейшая трехмерная фигура с плоскими сторонами. Его основные свойства озадачивали пытливые умы еще во времена Платона и Аристотеля. А в ноябре 2020 было опубликовано окончательное доказательство, в котором достоверно идентифицированы все существующие особые тетраэдры. В этой работе математики отвечают на вопрос о древней фигуре благодаря передовым технологиям, которые дают возможность использовать новый метод поиска решений определенных уравнений.
Юноше, обдумывающему электронику. Ключи к материалу для самостоятельного изучения
Информация
- В рейтинге
- Не участвует
- Откуда
- Москва и Московская обл., Россия
- Дата рождения
- Зарегистрирован
- Активность