CG & C++ blog
56 subscribers
13 photos
2 files
128 links
Краткий обзор публикаций, презентаций, докладов по графике и C++
Download Telegram
(video) CppCon 2016 - The speed of concurrency
Про оптимизацию lock-free контейнеров. Рассматриваются случаи, когда lock-free оказывается медленее блокирующих алгоритмов и как это исправить.

(video) CppCon 2015 - Live Lock-Free or Deadlock: part 1, part 2
И еще лекции от Fedor Pikus.
#cpp #lockfree #threading
Список тэгов

Программирование
#cpp - C++
#cpu_opt - оптимизации для ЦП
#atomics - атомарные операции, работа с кэшем
#threading - многопоточка
#lockfree - Lock free, wait free алгоритмы
#backend - сервера
#ecs - entity component system
#dod - data oriented design, низкоуровневая оптимизация

Графические API, работа на низком уровне
#gpu_opt - оптимизации для ГПУ
#gapi - все графические API
#vulkan #vk - Vulkan API
#metal - Apple Metal
#opengl #gl - OpenGL
#dx - DirectX 11, 12

Рендеринг
#cg - все что связано с компьютерной графикой
#proc_gen - процедурная генерация
#games - обзор технологий из игр

Другое
#news - новости по теме
#blog - новости по моим разработкам
#hw - все что связано с компьютерным железом
#desktop #win #mac #linux - относится к ПК, ноутбуки
#mobile #android #ios - относится к мобильным платфомам
#vr - VR, виртуальная реальность
GDC2018: Shadow of War: performance & memory optimization
Рассказывают про организацию потоков, выделение памяти через large pages, стриминг мипуровней.
Одна из немногих презентация про применение sparse memory.
#cpu_opt #threading #gpu_opt #sparse_mem
GDC2015: Destiny's multithreaded rendering architecture
Почти все про организацию системы тасков в движке под загрузку, подготовку, проверку видимости и рендеринг.
Слайды 60-66 - предлагают использовать системы:
object system
,
rendering
,
visibility
.
Компонент
visibility
отвечает за тест видимости и вычисление детализации, таким образом для rendering компонента будут подгружаться только необходимые данные.
#cpu_opt #ecs #threading
Запись в блоге про Job System 2.0: -1-, -2-, -3-, -4-, -5-
Используется классический алгоритм work stealing, но написано интересно.
#cpu_opt #threading
(video) Taskflow: A Parallel and Heterogeneous Task Programming System Using Modern C++
Исходники Taskflow
Taskflow - это очередная реализация job system, использующая все тот же work stealing алгоритм.
В видео сравнивается taskflow с популярными аналогами: TBB, OpenMP.

Мое мнение - сам подход устарел, здесь и в аналогах используется главный поток, который отправляет таски в другие потоки и ждет их завершения. Более правильный подход - когда весь код состоит из тасков.
Также многие библиотеки считают все потоки одинаковыми, тогда как на мобилках давно уже 2 или 3 типа ядер, и на ПК уже появились 2 типа ядер. Для более тонкой оптимизации нужно различать потоки с гипертредингом.
#cpp #threading
(video) CppCon 2020 - A Fully Asynchronous OS Based on Modern C++
Будущее за асинхронными ОС.
В C++ добавили корутины и таски, но ОС, поверх которого это сделано, имеет ограниченную поддержку асинхронщины, что снижает выигрыш от многопоточности.
#cpp #threading
(video) Tune CPU job scheduling for Apple silicon games
Рассказывают как устроен мобильный ЦП, как ОС распределяет работу по потокам.
В начале полезно для новичнов и чтобы освежить знания.
21:48 - рассказывают как организовать менеджер тасков с учетом E и P ядер и типа задач.
#cpu_opt #apple_cpu #threading
Какая должна быть многопоточность в ОС
Сейчас ОС управляет потоками, у кого выше приоритет, тот получает больше времени ядра ЦП. ОС может остановить поток в любой момент и запустить другой поток на этом ядре, может перекинуть поток на другое ядро.
Переключение между потоками очень дорогое (более 1мс), что не позволяет выделить по одному потоку на задачу, а несколько параллельно запущенных приложений могут начать конкуренцию за ЦП с большими потерями на переключение потоков.

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

Проблема решается заменой потоков на систему тасков в ОС, но это потребует переделать или отказаться от контекста потока.

Дальше можно оптимизировать доступ к памяти - делать загрузку из ОЗУ в кэш до запуска таска, чтобы сам таск выполнялся максимально быстро, например для модели типа ECS/DOD, где доступ к данным полностью предсказуем.
#threading #blog
(video) Tune CPU job scheduling for Apple silicon games
Рекомендации, как делать многопоточку на ЦП от Apple.
6:00 - оверхэд от запуска тасков на разных ядрах.
16:20 - как получить количество P и E ядер ЦП.
19:30 - LibDispatch для тех, кто не пишет свою систему тасков.
21:58 - выбор приоритетов для потоков.
#cpu_opt #threading #apple_cpu
Improving job system performance scaling in 2022.2
part 1: Background and API
part 2: Overhead
Рассказывают как работает планировщик задач в Юнити, какие у него узкие места и как они оптимизировали его в новой версии.
А проблемы типичные:
* проверка, завершены ли зависимые таски.
* потери на переключение потоков (context switch).
* задержка при пробуждении потока.
* синхронизации при большом количестве потоков, в том числе и при lock-free алгоритмах.
#threading
What is Low Latency C++? CppNow 2023

Part 1 (pdf) (video)
С 44:29 начинаются примеры микрооптимизаций.
56:26 - примеры использования assume.
1:06:15 - немного про новые атрибуты noalias, unsequenced и тд. Похоже компиляторы ни на что не способны и надо вручную выставлять атрибуты.

Part 2 (pdf) (video)
Разбирается что не надо делать в low-latency коде, тут больше про блокировки и нестабильное время выполнения.
Есть ссылка на интересную реализацию спинлока, где ожидание сделано с постепенным увеличением паузы: progressive_backoff_wait

#cpp #threading #lockfree
Как приостановить поток. Тесты на Mac M1 и Android.

Реализация std::this_thread::sleep_for() и sleep_until() под MacOS работает точнее, минимальное время 4-10мкс, далее результаты близки к требуемым, но погрешность может доходить до 20%. Например для 15мс результат 15.9мс, для 100мкс - 120мкс.

Кроме STD доступны и Unix функции nanosleep и usleep.
Функция nanosleep() со стандартными настройками минимальное время пазуы: 6мкс, для 10мкс - 17мкс, для 100мкс - 130мкс. Чем больше время ожидания, тем лучше точность, но всегда больше 10%.
Функция usleep() помечена как устаревшая и по точности не лучше nanosleep().

Для коротких пауз есть __builtin_arm_yield (аналоги __yield, asm volatile("yield")) что занимает около 30нс. В отличие от x86 с гипертредингом, эта инструкция не совершает никаких действий, только информирует ЦП, что не нужно снижать частоту. На Android девайсах с более низкой частотой инструкция выполняется дольше, так на Cortex A53 занимает 1-3мкс, а на A55 - 90нс. Вызов инструкции внутри цикла ничего не меняет.
На Windows компилятор инлайнит вызов _mm_pause() даже из cpp файла, а на Mac и Android - нет, поэтому при оборачивании инструкции в функцию следует разместить ее в хэдере и пометить как forceinline.

На ARM64 появилась инструкция WFE - Wait For Event (__builtin_arm_wfe, __wfe), которая переводит ЦП в экономичный режим в ожидании события. Если не использовать механизм событий, то функция приостановит поток на фиксированное время - ARM_BOARD_WFE_TIMEOUT_NS, что около 1мкс.

Получаются предсказуемые интервалы:
30нс-3мкс для __builtin_arm_yield
1-30мкс для __builtin_arm_wfe
500мкс для nanosleep(420us)
15мс для sleep_for(15ms)

Тесты на Windows
#cpp #threading