REVERSE13 Telegram 689
В общем накипело.
atomic wait/notify и все связанное c этой фичей в C++20 просто сломано причем в куче мест

Давайте разберемся по пунктам:

Начнем с апи, стандарта, оно неправильное
1.1) Неправильно требовать валидный *this для нотификации.
Ведь в большинстве юзкейсов у нас его уже нет, а в имплементациях нам он не нужен.
На эту тему есть proposal, единственное маленькое уточнение, такой код логичнее, чем тот что приводит в примере Льюс Бейкер
1.2) Менее важный момент, что wait ждет изменения значения, мы сразу сталкиваемся с кучей проблем, подробнее дальше, но вот краткий список:
spurious wakeups (мы должны их обрабатывать), пропуск нотификаций, изменение значение без нотификаций и так далее
Резюмирую: wait и notify обязаны были быть кроссплатформенными обертками над сисколами

Дальше про проблемы имплементаций:
2) Вроде все неплохо в MSVC STL, так как на винде есть WaitOnAddress для 1, 2, 4, 8 байт, реализация же вроде работает без багов и делает что-то разумное:
Делает load с нужным memory order и вызывает системную имплементацию

Загрузка wait функций страшная и непонятно насколько правильна fallback реализация, но лично мне пофиг на древнюю винду.
По поводу загрузки кажется как минимум то, что на вызов делается 2 atomic load можно было бы поправить:
1. https://github.com/microsoft/STL/blob/8ca7bd3c002d383940de9abe6379721e96eb12e3/stl/src/atomic_wait.cpp#L163
2. https://github.com/microsoft/STL/blob/8ca7bd3c002d383940de9abe6379721e96eb12e3/stl/src/atomic_wait.cpp#L173
Но наверно на фоне сискола это незначительно.

И тут мы плавно переходим к проблеме других реализаций, как можно поправить то что syscall дорогой.
Ну например добавив счетчик сколько сейчас ждет, или spin c cpu_relax/etc сколько-то итераций.

Нужно ли это делать? НЕТ.
А если вдруг хочется оптимально имплементировать wait, для этого есть condvar, semaphore, etc
Поэтому спасибо разработчикам MSVC STL за хорошую реализацию (кстати второй раз натыкаюсь на то, что остальные сделали плохо, а они хорошо, первый visit variant).

Как мы помним у MSVC все хорошо отчасти потому что WaitOnAddress работает с атомиками sizeof 1,2,4,8.
На линуксе же это не так, как многие из вас знаю futex требует uint32_t, а в принципе работает с любым 32 битным адресом.
Так что дальше будет хуже.
В принципе, чтобы это исправить (а на самом деле для windows софта в wine/proton) добавили futex2 в ядре 5.16
К сожалению оно пока больше про другие возможности Wait/WakeOnAddress, то есть все еще только 32 битное.
Да и даже так ни одна stdlib пока не поддерживает, и хорошо если поддержит лет через 10.

3) Возникла мысль, что ничего страшного ведь для 32 битных атомиков все будет как на винде?
Для libc++ действительно практически так, но есть пара нюансов:
3.1) Перед сисколом будет spin в wait, то есть до сискола мы будем крутиться (если что там выше по стеку проверяется каждую итерацию значение атомика, первые 64 итерации now() не вызывают), в чем проблема? Другие реализации могут иметь другой спин, не кроссплатформенно
3.2) Эта реализация будет использоваться только в случае, если у вас linux и atomic_int32_t.
Почему не разрешить для других подходящих по sizeof и alignment типов? Потому что им пофиг, написали, галочку, что поддержали, поставили и идите вы все в жопу.
3.3) Какая же реализация в случае других типов или других операционных систем?
Берется хеш адреса вашего атомика и выбирается ячейка из двух 32 битных атомиков в таблице на 256 ячеек
Один из атомиков используется для подсчета сколько сейчас ждет потоков в этой ячейке (и оптимизации: не нужно делать нотификацию если нет тех кто спит)
Другой для ожидания на сисколе (кстати теоритически можно смоделировать ситуацию что мы пропустим нотификацию из-за переполнения 31 бит (хотя там уб в таком случае так как signed)
3.4) Кстати, а как пользователь должен узнавать какой тип отвечает за нативное ожидания? int32 или что то еще?
В стандарте добавили atomic_signed_lock_free, atomic_unsigned_lock_free, которыех к сожалению нет libstdc++, а в libc++ они 64 битные :)
👍3



tgoop.com/reverse13/689
Create:
Last Update:

В общем накипело.
atomic wait/notify и все связанное c этой фичей в C++20 просто сломано причем в куче мест

Давайте разберемся по пунктам:

Начнем с апи, стандарта, оно неправильное
1.1) Неправильно требовать валидный *this для нотификации.
Ведь в большинстве юзкейсов у нас его уже нет, а в имплементациях нам он не нужен.
На эту тему есть proposal, единственное маленькое уточнение, такой код логичнее, чем тот что приводит в примере Льюс Бейкер
1.2) Менее важный момент, что wait ждет изменения значения, мы сразу сталкиваемся с кучей проблем, подробнее дальше, но вот краткий список:
spurious wakeups (мы должны их обрабатывать), пропуск нотификаций, изменение значение без нотификаций и так далее
Резюмирую: wait и notify обязаны были быть кроссплатформенными обертками над сисколами

Дальше про проблемы имплементаций:
2) Вроде все неплохо в MSVC STL, так как на винде есть WaitOnAddress для 1, 2, 4, 8 байт, реализация же вроде работает без багов и делает что-то разумное:
Делает load с нужным memory order и вызывает системную имплементацию

Загрузка wait функций страшная и непонятно насколько правильна fallback реализация, но лично мне пофиг на древнюю винду.
По поводу загрузки кажется как минимум то, что на вызов делается 2 atomic load можно было бы поправить:
1. https://github.com/microsoft/STL/blob/8ca7bd3c002d383940de9abe6379721e96eb12e3/stl/src/atomic_wait.cpp#L163
2. https://github.com/microsoft/STL/blob/8ca7bd3c002d383940de9abe6379721e96eb12e3/stl/src/atomic_wait.cpp#L173
Но наверно на фоне сискола это незначительно.

И тут мы плавно переходим к проблеме других реализаций, как можно поправить то что syscall дорогой.
Ну например добавив счетчик сколько сейчас ждет, или spin c cpu_relax/etc сколько-то итераций.

Нужно ли это делать? НЕТ.
А если вдруг хочется оптимально имплементировать wait, для этого есть condvar, semaphore, etc
Поэтому спасибо разработчикам MSVC STL за хорошую реализацию (кстати второй раз натыкаюсь на то, что остальные сделали плохо, а они хорошо, первый visit variant).

Как мы помним у MSVC все хорошо отчасти потому что WaitOnAddress работает с атомиками sizeof 1,2,4,8.
На линуксе же это не так, как многие из вас знаю futex требует uint32_t, а в принципе работает с любым 32 битным адресом.
Так что дальше будет хуже.
В принципе, чтобы это исправить (а на самом деле для windows софта в wine/proton) добавили futex2 в ядре 5.16
К сожалению оно пока больше про другие возможности Wait/WakeOnAddress, то есть все еще только 32 битное.
Да и даже так ни одна stdlib пока не поддерживает, и хорошо если поддержит лет через 10.

3) Возникла мысль, что ничего страшного ведь для 32 битных атомиков все будет как на винде?
Для libc++ действительно практически так, но есть пара нюансов:
3.1) Перед сисколом будет spin в wait, то есть до сискола мы будем крутиться (если что там выше по стеку проверяется каждую итерацию значение атомика, первые 64 итерации now() не вызывают), в чем проблема? Другие реализации могут иметь другой спин, не кроссплатформенно
3.2) Эта реализация будет использоваться только в случае, если у вас linux и atomic_int32_t.
Почему не разрешить для других подходящих по sizeof и alignment типов? Потому что им пофиг, написали, галочку, что поддержали, поставили и идите вы все в жопу.
3.3) Какая же реализация в случае других типов или других операционных систем?
Берется хеш адреса вашего атомика и выбирается ячейка из двух 32 битных атомиков в таблице на 256 ячеек
Один из атомиков используется для подсчета сколько сейчас ждет потоков в этой ячейке (и оптимизации: не нужно делать нотификацию если нет тех кто спит)
Другой для ожидания на сисколе (кстати теоритически можно смоделировать ситуацию что мы пропустим нотификацию из-за переполнения 31 бит (хотя там уб в таком случае так как signed)
3.4) Кстати, а как пользователь должен узнавать какой тип отвечает за нативное ожидания? int32 или что то еще?
В стандарте добавили atomic_signed_lock_free, atomic_unsigned_lock_free, которыех к сожалению нет libstdc++, а в libc++ они 64 битные :)

BY Loser story


Share with your friend now:
tgoop.com/reverse13/689

View MORE
Open in Telegram


Telegram News

Date: |

Channel login must contain 5-32 characters Informative SUCK Channel Telegram The public channel had more than 109,000 subscribers, Judge Hui said. Ng had the power to remove or amend the messages in the channel, but he “allowed them to exist.” 2How to set up a Telegram channel? (A step-by-step tutorial)
from us


Telegram Loser story
FROM American