⚡️ Один `static` - три разных смысла. Добро пожаловать в C.
В C ключевое слово
### 1.
Переменная имеет internal linkage - она доступна только внутри текущего
Это удобный способ спрятать детали реализации модуля.
### 2.
Он существует всё время работы программы и сохраняет значение между вызовами функции.
### 3.
Функция становится видна только внутри текущего translation unit.
Другой
Итого:
🔥 Поэтому
lifetime и linkage.
#C #Programming #SystemsProgramming #LowLevel #Cpp
В C ключевое слово
static меняет поведение в зависимости от того, где именно оно написано.### 1.
static у глобальной переменной
static int global;
Переменная имеет internal linkage - она доступна только внутри текущего
.c файла.Это удобный способ спрятать детали реализации модуля.
### 2.
static внутри функции
void foo(void) {
static int count;
count++;
}
count не создаётся заново при каждом вызове.Он существует всё время работы программы и сохраняет значение между вызовами функции.
foo(); // count = 1
foo(); // count = 2
foo(); // count = 3
### 3.
static у функции
static void bar(void) {
}
Функция становится видна только внутри текущего translation unit.
Другой
.c файл вызвать bar() напрямую уже не сможет.Итого:
static global variable -> скрыть символ внутри файла
static local variable -> сохранить состояние между вызовами
static function -> скрыть функцию внутри файла
🔥 Поэтому
static в C полезнее воспринимать не как одно конкретное поведение, а как подсказку проверить две вещи:lifetime и linkage.
#C #Programming #SystemsProgramming #LowLevel #Cpp
👍17🔥9❤6❤🔥1
🎶 Оптимизированный аудиовизуализатор для Windows
Spectrum — это легковесный аудиовизуализатор на C++, который обрабатывает звук в реальном времени и выводит его в консоль без разрывов экрана. Он использует FFTW3 для анализа аудиосигналов и обеспечивает точное визуальное представление частот.
🚀 Основные моменты:
- Реализация на C++17 для Windows.
- Низкое использование CPU и памяти.
- Поддержка WASAPI для захвата системного звука.
- Отображение в виде ASCII-графиков.
- Легкий в использовании и установке.
📌 GitHub: https://github.com/majockbim/spectrum
#cpp
Spectrum — это легковесный аудиовизуализатор на C++, который обрабатывает звук в реальном времени и выводит его в консоль без разрывов экрана. Он использует FFTW3 для анализа аудиосигналов и обеспечивает точное визуальное представление частот.
🚀 Основные моменты:
- Реализация на C++17 для Windows.
- Низкое использование CPU и памяти.
- Поддержка WASAPI для захвата системного звука.
- Отображение в виде ASCII-графиков.
- Легкий в использовании и установке.
📌 GitHub: https://github.com/majockbim/spectrum
#cpp
GitHub
GitHub - majockbim/spectrum: >_ audio visualization in your terminal
>_ audio visualization in your terminal. Contribute to majockbim/spectrum development by creating an account on GitHub.
👍7❤3🔥2
💡 Clang умеет показывать AST, и это один из лучших способов реально понять, что компилятор видит в вашем C/C++ коде.
AST — это Abstract Syntax Tree, внутреннее представление программы после парсинга.
Например, простой код:
для компилятора — не просто строка текста, а дерево примерно такого смысла:
Именно через такое представление компилятор понимает структуру выражений, типы, области видимости и то, какие преобразования можно выполнить дальше.
У Clang AST можно получить напрямую:
А в Compiler Explorer / Godbolt есть отдельный режим просмотра AST, поэтому можно менять код и сразу видеть, как перестраивается дерево.
Особенно полезно разбирать так:
* шаблоны;
* перегрузку функций;
* implicit conversions;
*
* лямбды;
* range-based
* временные объекты;
* разные формы инициализации.
Если регулярно смотреть AST, C++ постепенно перестаёт выглядеть как набор «магических правил».
Начинаешь видеть код примерно так, как его видит компилятор.
🔗
#Cpp #Clang #Compiler #Programming
AST — это Abstract Syntax Tree, внутреннее представление программы после парсинга.
Например, простой код:
int x = a + b * 2;
для компилятора — не просто строка текста, а дерево примерно такого смысла:
VarDecl
└── BinaryOperator +
├── a
└── BinaryOperator *
├── b
└── 2
Именно через такое представление компилятор понимает структуру выражений, типы, области видимости и то, какие преобразования можно выполнить дальше.
У Clang AST можно получить напрямую:
clang++ -Xclang -ast-dump -fsyntax-only main.cpp
А в Compiler Explorer / Godbolt есть отдельный режим просмотра AST, поэтому можно менять код и сразу видеть, как перестраивается дерево.
Особенно полезно разбирать так:
* шаблоны;
* перегрузку функций;
* implicit conversions;
*
auto;* лямбды;
* range-based
for;* временные объекты;
* разные формы инициализации.
Если регулярно смотреть AST, C++ постепенно перестаёт выглядеть как набор «магических правил».
Начинаешь видеть код примерно так, как его видит компилятор.
🔗
https://godbolt.org/z/cfc7h41bT#Cpp #Clang #Compiler #Programming
👍19🔥8🥰4❤2💯1
📚 Библиотека для работы с SQLite в C++26 с использованием рефлексии
Reflite — это библиотека на C++26, которая упрощает взаимодействие с SQLite, позволяя использовать обычные структуры как основу для выполнения запросов. Она поддерживает основные операции: вставка, удаление, выборка и обновление, избавляя от лишнего шаблона кода.
🚀 Основные моменты:
- Легковесная библиотека в одном файле
- Поддержка операций INSERT, DELETE, SELECT, UPDATE
- Использует рефлексию для работы с типами структур
- Не требует полной реализации SQL, фокус на простоте
- Совместима с современными компиляторами C++26
📌 GitHub: https://github.com/KaruroChori/reflite
#cpp
Reflite — это библиотека на C++26, которая упрощает взаимодействие с SQLite, позволяя использовать обычные структуры как основу для выполнения запросов. Она поддерживает основные операции: вставка, удаление, выборка и обновление, избавляя от лишнего шаблона кода.
🚀 Основные моменты:
- Легковесная библиотека в одном файле
- Поддержка операций INSERT, DELETE, SELECT, UPDATE
- Использует рефлексию для работы с типами структур
- Не требует полной реализации SQL, фокус на простоте
- Совместима с современными компиляторами C++26
📌 GitHub: https://github.com/KaruroChori/reflite
#cpp
🔥10👍4❤2🥰1👌1
Fenwick Tree, или Binary Indexed Tree, считает prefix sums за O(log n).
Вся магия в операции:
i & -i
Она находит младший установленный бит числа.
Почему это работает?
В two’s complement число
-i получается как инверсия битов i плюс 1.Когда мы делаем
i & -i, остаётся только самый правый бит, равный 1.Например:
i = 12 // 1100
-i // 0100 в нужной маске
i & -i = 4
Именно это значение говорит Fenwick Tree, на сколько нужно прыгнуть по индексам.
Для обновления:
for (; i < MAXN; i += i & -i)
tree[i] += v;
Мы идём вверх по структуре и обновляем все узлы, которые покрывают этот индекс.
Для запроса суммы:
for (; i > 0; i -= i & -i)
s += tree[i];
Мы идём вниз и собираем нужные блоки суммы.
Одна и та же операция управляет двумя направлениями:
*
i += i & -i — перейти к следующему ответственному узлу*
i -= i & -i — убрать последний блок из prefix sumПоэтому Fenwick Tree такой компактный:
никаких явных рёбер, указателей и рекурсии. Только массив и битовая арифметика.
Красота структуры в том, что дерево как бы спрятано внутри двоичного представления индекса.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤4🔥2
⚙️ Обычный
Причина в том, что
Чем длиннее буфер, тем больше данных приходится повторно проходить.
Например:
В бенчмарке сборка строки примерно на 1 МБ заняла около 4,1 секунды.
Если же заранее выделить буфер и просто хранить текущую позицию записи:
тот же объём собирается примерно за 0,4 мс.
Разница больше чем в 10 000 раз.
Мелочь, которую легко пропустить: проблема не в копировании строки, а в постоянном повторном поиске её конца.
strcat() в цикле может незаметно превратить простую склейку строк в O(n²).Причина в том, что
strcat() при каждом вызове сначала ищет конец уже собранной строки.Чем длиннее буфер, тем больше данных приходится повторно проходить.
Например:
for (int i = 0; i < 100000; i++)
strcat(buf, "chunk");
В бенчмарке сборка строки примерно на 1 МБ заняла около 4,1 секунды.
Если же заранее выделить буфер и просто хранить текущую позицию записи:
char *p = buf;
for (int i = 0; i < 100000; i++) {
memcpy(p, "chunk", 5);
p += 5;
}
тот же объём собирается примерно за 0,4 мс.
Разница больше чем в 10 000 раз.
Мелочь, которую легко пропустить: проблема не в копировании строки, а в постоянном повторном поиске её конца.
❤15
Это как раз то, что делает
madvise(MADV_DONTNEED) для anonymous mappings.Сценарий такой:
char *region = mmap(NULL, GB,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
// потрогали часть страниц
madvise(region, GB, MADV_DONTNEED);
После
madvise виртуальные адреса остаются валидными. Процесс всё ещё «видит» тот же диапазон памяти.Но физические страницы, которые стояли за этим диапазоном, ядро может забрать обратно. То есть адресное пространство осталось, а реальная RAM освободилась.
При следующем обращении к этому участку процесс получит свежие zero-filled страницы. Старых данных там уже не будет.
Почему это полезно:
* можно держать большой виртуальный регион без постоянного удержания RAM
* аллокаторы могут возвращать неиспользуемые страницы ядру
* long-running процессы меньше раздувают RSS
* память можно переиспользовать без полного
munmap и нового mmapВажная деталь:
MADV_DONTNEED не означает «удали адреса». Это скорее сигнал ядру: «эти страницы мне сейчас не нужны, можешь забрать физическую память».Адреса остаются. Страницы уходят. Следующее чтение приносит нули.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤🔥2🥰2❤1
Проблема не в atomics.
Проблема в том, что один поток уже убрал узел из структуры, а другой всё ещё может его читать.
Удалишь слишком рано, получишь use-after-free.
Поэтому в C++26 стандартизируют Hazard Pointers.
Идея простая:
поток заранее помечает объект как “я сейчас его читаю”.
Пока хотя бы один reader держит такой hazard pointer, объект нельзя удалять.
Удаление откладывается до момента, когда все читатели закончат работу.
Это делает lock-free структуры вроде стеков, очередей и списков намного безопаснее.
Lock-free программирование становится не магией, а чуть более нормальным инженерным инструментом.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15❤6👍4
Кто-то под именем Сатоши Накамото в 2008 году опубликовал идею, из которой выросла целая индустрия майнинга с огромным энергопотреблением.
И до сих пор никто достоверно не знает, кто скрывается за этим именем.
При этом сама базовая идея Proof of Work выглядит почти примитивно: берём число nonce, меняем его снова и снова, каждый раз считаем хэш и проверяем, попал ли результат ниже нужного target.
Условно это выглядит так:
То есть майнинг Bitcoin в основе своей это гигантский перебор чисел с постоянным пересчётом SHA-256.
Простой цикл, который в итоге породил ASIC-фермы, энергопотребление в масштабах стран и индустрию на миллиарды долларов.
И до сих пор никто достоверно не знает, кто скрывается за этим именем.
При этом сама базовая идея Proof of Work выглядит почти примитивно: берём число nonce, меняем его снова и снова, каждый раз считаем хэш и проверяем, попал ли результат ниже нужного target.
Условно это выглядит так:
uint32_t nonce = 0;
while (1) {
header.nonce = nonce;
hash = sha256(sha256(header));
if (hash < target)
break;
nonce++;
}
То есть майнинг Bitcoin в основе своей это гигантский перебор чисел с постоянным пересчётом SHA-256.
Простой цикл, который в итоге породил ASIC-фермы, энергопотребление в масштабах стран и индустрию на миллиарды долларов.
❤14🔥5👍2
🔥 Хочешь быстрее расти в IT? Хватит учиться в одиночку
Окружение решает больше, чем кажется.
Собрал папки и каналы, где можно быстрее влиться в нужное направление, следить за трендами и не вариться в своём пузыре.
AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: https://xn--r1a.website/+90Z5TAyfuNU5YmRi
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_1001_notes
Java: t.me/javatg
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: https://xn--r1a.website/gamedev
Haskell: t.me/haskell_tg
Собеседования и карьера:
DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview
Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: https://xn--r1a.website/addlist/2Ls-snqEeytkMDgy
Папка Frontend: https://xn--r1a.website/addlist/mzMMG3RPZhY2M2Iy
Полезное сверху:
ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: https://xn--r1a.website/+rKBQEMccAA01MTcy
ИТ-книги бесплатно: https://xn--r1a.website/addlist/BkskQciUW_FhNjEy
Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg
Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.
Окружение решает больше, чем кажется.
Собрал папки и каналы, где можно быстрее влиться в нужное направление, следить за трендами и не вариться в своём пузыре.
AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: https://xn--r1a.website/+90Z5TAyfuNU5YmRi
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_1001_notes
Java: t.me/javatg
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: https://xn--r1a.website/gamedev
Haskell: t.me/haskell_tg
Собеседования и карьера:
DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview
Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: https://xn--r1a.website/addlist/2Ls-snqEeytkMDgy
Папка Frontend: https://xn--r1a.website/addlist/mzMMG3RPZhY2M2Iy
Полезное сверху:
ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: https://xn--r1a.website/+rKBQEMccAA01MTcy
ИТ-книги бесплатно: https://xn--r1a.website/addlist/BkskQciUW_FhNjEy
Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg
Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.
❤5👍2🔥2🤔1
Одна строка C, которая может сломать вам логику
В C порядок вычисления аргументов функции не определён.
Из-за этого один и тот же код может дать разный результат:
* gcc:
* clang:
Причина простая: компиляторы по-разному вычисляют аргументы.
Такие вещи годами становились источником очень неприятных багов.
Хорошая новость: сейчас
Вывод банальный, но важный: не пишите код, который зависит от порядка вычисления аргументов.
В C порядок вычисления аргументов функции не определён.
foo(i++, i++);
Из-за этого один и тот же код может дать разный результат:
* gcc:
foo(1, 0)* clang:
foo(0, 1)Причина простая: компиляторы по-разному вычисляют аргументы.
Такие вещи годами становились источником очень неприятных багов.
Хорошая новость: сейчас
-Wall обычно умеет это подсветить.Вывод банальный, но важный: не пишите код, который зависит от порядка вычисления аргументов.
❤16👍8🥰3
В C есть синтаксис, который выглядит как опечатка:
Кажется, что такой
Но в GCC это работает. Это расширение называется case ranges — можно задавать сразу диапазон значений внутри
Например:
Вместо десяти отдельных
Но есть нюанс: это не стандартный C, а расширение GCC. Если код должен быть переносимым между компиляторами, на такой синтаксис лучше не рассчитывать.
Одна из тех возможностей C, которые выглядят неправильно, пока не узнаешь, что компилятор действительно это поддерживает.
case '0' ... '9':
Кажется, что такой
switch вообще не должен компилироваться.Но в GCC это работает. Это расширение называется case ranges — можно задавать сразу диапазон значений внутри
case.Например:
case '0' ... '9':
return DIGIT;
case 'a' ... 'z':
case 'A' ... 'Z':
return LETTER;
Вместо десяти отдельных
case для цифр и ещё десятков для букв — одна строка на диапазон.Но есть нюанс: это не стандартный C, а расширение GCC. Если код должен быть переносимым между компиляторами, на такой синтаксис лучше не рассчитывать.
Одна из тех возможностей C, которые выглядят неправильно, пока не узнаешь, что компилятор действительно это поддерживает.
🔥26👍7❤6✍2🥰1
Частая ошибка:
for (int i = 0; i < n; i++) {
int j = rand() % n;
swap(a[i], a[j]);
}
На вид всё нормально: каждый элемент случайно меняется местами с другим.
Но проблема в вероятностях.
Для массива из n элементов существует n! перестановок.
Хороший shuffle должен давать каждой перестановке одинаковый шанс.
Наивный вариант делает n шагов, и на каждом шаге выбирает индекс из полного диапазона 0..n-1.
В итоге некоторые перестановки появляются чаще других.
Правильный подход - Fisher-Yates shuffle:
for (int i = n - 1; i > 0; i--) {
int j = random(0, i);
swap(a[i], a[j]);
}
Идея простая:
на каждом шаге мы выбираем элемент только из ещё не зафиксированной части массива.
Сначала выбираем последний элемент из всего массива.
Потом предпоследний - из оставшихся.
Потом следующий - из ещё меньшего диапазона.
Так каждая перестановка получает одинаковую вероятность.
В C++ лучше не писать через rand() % n, потому что там может быть ещё и modulo bias.
Нормальный вариант:
std::mt19937 rng(std::random_device{}());
for (int i = n - 1; i > 0; --i) {
std::uniform_int_distribution<int> dist(0, i);
int j = dist(rng);
std::swap(a[i], a[j]);
}
Shuffle - хороший пример, где код может выглядеть “рандомным”, но математически быть неправильным.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8❤🔥5👍1
✈️🌍 FlightGear: мощный симулятор полетов с открытым исходным кодом.
Созданный для исследователей и энтузиастов авиации, FlightGear предлагает реалистичную симуляцию полетов с поддержкой множества самолетов и ландшафтов. Проект активно развивается сообществом, предоставляя возможность пользователям вносить свой вклад и улучшать опыт.
🚀Основные моменты:
- Поддержка множества типов самолетов и ландшафтов.
- Реалистичная физика полета и погодные условия.
- Многофункциональный интерфейс и расширяемая архитектура.
- Активное сообщество разработчиков и пользователей.
- Кроссплатформенная доступность.
📌 GitHub: https://github.com/FlightGear/flightgear
#c++
Созданный для исследователей и энтузиастов авиации, FlightGear предлагает реалистичную симуляцию полетов с поддержкой множества самолетов и ландшафтов. Проект активно развивается сообществом, предоставляя возможность пользователям вносить свой вклад и улучшать опыт.
🚀Основные моменты:
- Поддержка множества типов самолетов и ландшафтов.
- Реалистичная физика полета и погодные условия.
- Многофункциональный интерфейс и расширяемая архитектура.
- Активное сообщество разработчиков и пользователей.
- Кроссплатформенная доступность.
📌 GitHub: https://github.com/FlightGear/flightgear
#c++
👍10❤3
Первый релиз вышел 20 марта 1998 года. Его запустил один разработчик - Daniel Stenberg.
Прошло больше 27 лет, а он всё ещё поддерживает проект.
Сегодня
curl работает на миллиардах устройств и поставляется почти везде:* macOS
* основные Linux-дистрибутивы
* Windows 10 и новее
* серверы
* контейнеры
* embedded-системы
* CI/CD пайплайны
Ирония в том, что многие пользуются
curl каждый день, даже не думая об этом.Одна маленькая CLI-утилита стала невидимой инфраструктурой интернета.
Вот так выглядит настоящий open source: без хайпа, без миллиардных раундов, но с кодом, который держит половину мира.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26❤9🥰2
❓Кто этот призрак в вашем коде: изучаем особенности работы с легаси на C++
Легаси — вот что объединяет всех разработчиков на всех языках программирования. Мы учимся уживаться с «наследием», встраиваем его в современную кодовую базу или стараемся не трогать.
Пришло время разобраться с легаси в email-проекте Ghost in the code.
Вы получите семь писем от инженеров, в числе которых представитель России в Международной рабочей группе по стандартизации C++ Антон Полухин и эксперт по архитектуре Константин Владимиров. Вместе с ними и другими опытным разработчиками пройдете путь от навигации по «зрелому» коду с помощью AI до выстраивания процессов с учетом легаси.
➡️Подписывайтесь на серию писем, это бесплатно. Оставляйте email-адрес на сайте проекта — первое письмо придет 15 сентября.
Легаси — вот что объединяет всех разработчиков на всех языках программирования. Мы учимся уживаться с «наследием», встраиваем его в современную кодовую базу или стараемся не трогать.
Пришло время разобраться с легаси в email-проекте Ghost in the code.
Вы получите семь писем от инженеров, в числе которых представитель России в Международной рабочей группе по стандартизации C++ Антон Полухин и эксперт по архитектуре Константин Владимиров. Вместе с ними и другими опытным разработчиками пройдете путь от навигации по «зрелому» коду с помощью AI до выстраивания процессов с учетом легаси.
➡️Подписывайтесь на серию писем, это бесплатно. Оставляйте email-адрес на сайте проекта — первое письмо придет 15 сентября.
❤5👍4
Как Linux увеличивает счётчик без lock на SMP-системах
В ядре Linux есть трюк, который выглядит почти слишком просто: не заставлять все CPU драться за одну переменную.
Вместо общего счётчика используется per-CPU переменная - у каждого ядра своя копия данных.
На x86 макрос
Что это даёт:
* нет общего lock
* нет постоянной конкуренции между ядрами
* инкремент выполняется локально для текущего CPU
* операция получается быстрой и дешёвой
Идея мощная: если данные можно разделить по CPU, не нужно синхронизировать каждый маленький апдейт между всеми ядрами.
Так ядро экономит огромное количество лишней блокировки там, где код выполняется постоянно.
В ядре Linux есть трюк, который выглядит почти слишком просто: не заставлять все CPU драться за одну переменную.
Вместо общего счётчика используется per-CPU переменная - у каждого ядра своя копия данных.
На x86 макрос
this_cpu_inc(var) превращается в одну инструкцию incl, которая работает с областью данных текущего CPU через GS.Что это даёт:
* нет общего lock
* нет постоянной конкуренции между ядрами
* инкремент выполняется локально для текущего CPU
* операция получается быстрой и дешёвой
Идея мощная: если данные можно разделить по CPU, не нужно синхронизировать каждый маленький апдейт между всеми ядрами.
Так ядро экономит огромное количество лишней блокировки там, где код выполняется постоянно.
🔥16❤🔥5👍4❤3
🔥 Джулиан Сторер - разработчик с более чем 30-летним опытом C++
Он создал сразу несколько заметных проектов в мире аудио-разработки:
- Tracktion DAW
- JUCE C++ Framework
- Cmajor DSP language
Особенно интересно тем, кто работает с:
- C++
- аудио и музыкой
- DSP
- DAW
- real-time приложениями
У него много сильного open-source кода и проектов, которые стоит изучить разработчикам из audio/software engineering.
https://github.com/julianstorer
Он создал сразу несколько заметных проектов в мире аудио-разработки:
- Tracktion DAW
- JUCE C++ Framework
- Cmajor DSP language
Особенно интересно тем, кто работает с:
- C++
- аудио и музыкой
- DSP
- DAW
- real-time приложениями
У него много сильного open-source кода и проектов, которые стоит изучить разработчикам из audio/software engineering.
https://github.com/julianstorer
👍17❤5❤🔥2
3D-фрактал Mandelbulb можно отрендерить примерно в 100 строках C++ - вообще без полноценного 3D-движка.
В основе всего несколько идей:
- Mandelbulb строится через сферическую итерацию в степени 8
- distance estimator примерно определяет расстояние до поверхности фрактала
- sphere tracing двигает луч большими шагами через пустое пространство
- когда луч приближается к поверхности, конечные разности вычисляют нормаль для освещения
- результат записывается напрямую в обычный PPM-файл
То есть сложнейший на вид 3D-фрактал получается из математики, ray marching и небольшого количества C++.
Особенно красиво здесь то, что геометрия вообще не хранится в виде миллионов полигонов - поверхность вычисляется прямо во время рендера.
В основе всего несколько идей:
- Mandelbulb строится через сферическую итерацию в степени 8
- distance estimator примерно определяет расстояние до поверхности фрактала
- sphere tracing двигает луч большими шагами через пустое пространство
- когда луч приближается к поверхности, конечные разности вычисляют нормаль для освещения
- результат записывается напрямую в обычный PPM-файл
То есть сложнейший на вид 3D-фрактал получается из математики, ray marching и небольшого количества C++.
Особенно красиво здесь то, что геометрия вообще не хранится в виде миллионов полигонов - поверхность вычисляется прямо во время рендера.
🔥17❤3👍2