Ну да, сам wasm это скорее спецификация. Виртульной машиной наверное можно назвать какой-то wasmtime. Но в общем-то смысл же тот же, что и в jvm - компилим один раз в байткод и запускаем везде. Даже ограничения похожие - нет прямого доступа к окружению, только через интерфейсы "рантайма"
Кому просто обнаружить? Банки может и имеют такие возможности, и то не уверен что это проверяется через отправку SMS. Может мобильное приложение как-то может узнать ID симки или ещё как-то (на это маловероятно). А вот простые бизнесмены скорее всего пойдут лесом и не получат такой возможности. Кроме того мы ведь говорим не про авторизацию по ID симки, а про ввод кода, который послали на номер телефона. Ничего кроме этого кода веб-сервис от пользователя не получит. А от сотовых операторов он получит только счёт на оплату SMS. Поэтому без двухфакторной авторизации, только с одним OTP, полученном через SMS, лучше не рассчитывать на безопасность своих данных в сервисе. И про это скорее всего написано в оферте сервиса. Что-то вроде: "Если вы не удалили свой аккаунт перед тем как протерять свой номер телефона, то вы сам себе буратино, мы ни чего вам не гарантируем."
Бинго! И это прям красный флаг, который лучше не игнорить. Если сервис использует только проверку по SMS, поддерживает номера любых операторов и хранит что-то личное, то лучше его не использовать. Если сервис обслуживает клиентов только конкретного оператора, то у него есть возможность узнать о смене владельца номера. В этом случае чуть более надёжно получается. Если забыть про то, что sms в приципе не надёжны.
Если сервис просто показывает киношки и музыку, то эта проблема с авторизацией не так важна.
В этом контексте телега даже лучше получается. Можно получить user_id без необходимости договариваться с пачкой сотовых операторов, которые даже разговаривать с тобой не будут о такой интегарции.
Новый владелец номера может создать свой аккаунт телеги на этот номер. А потом пойти в сервис "МоиСамыеСекретныеДокументы.ком" и авторизоваться в нём используя код из телеги. И если этот сервис не проверит, что user_id, привязанный к номеру телефона, изменился, то новый владелец номера получит доступ к документам предыдущего владельца.
Телега сможет подтвердить только то, что у юзера в данный момент есть доступ к аккаунту с указанным номером телефона. То что номер телефона принадлежит этому человеку, телега гарантировать не может. Т.к. можно продолжать пользоваться авторизованным клиентом телеги до тех пор, пока новый владелец номера не решит создать свой аккаунт в телеге. Вот если они предоставляют в том числе какой-то уникальный ID юзера, тогда это можно будет использовать для авторизации в сервисах, которые хранят персональные данные и/или личный контент пользователей.
Спасибо за инструкцию. Сделал у себя в AX3 по аналогии связку: hev-socks5-tunnel -> Socks5-XRay ----> XRay Server
До этого использовал "порт-мапинг" для проброса WireGuard: WG -> dokodemo-door-XRay ----> XRay Server -> WG Но это работало очень медленно - 62 Мбит/с на скачивание при ширине канала 700 Мбит/сек. Почему так - не понятно. CPU роутера, можно сказать, был не нагружен.
Теперь, через hev-socks5-tunnel, у меня разгоняется до 230Мбит/сек, при общей нагрузке на CPU 50-60%. Это конечно сильно лучше чем было с WG, но не идеально. Если напрямую, в обход tun2socks, подключится браузером через Sock5 к XRay, то выдаёт 600 Мбит/сек. Судя по распределению нагрузки на ядра роутера, hev-socks5-tunnel работает как будто в один поток. Только одно ядро из 4-её грузит на 100%, а остальные болтаются в районе 30-50%.
Так же пробовал вариант с использованием WireGuard inbound-а в XRay, но это тоже работало очень медленно. По моему даже хуже чем с порт-мапингом.
Для inbound-ов можно прописать только порт. По дефолту оно будет слушать на всех интерфейсах контейнера. Не придётся менять конфиг xray при изменении IP адреса контейнера.
Ну да, механизм вытесняющей многозадачности, скорее всего сложно сделать без аппаратных прерываний. Иначе, как в современных асинхронных фреймворках, можно сделать кооперативную многозадачность - тут можно и без использования прерываний обойтись.
Прерывание выполнение потока не важно в этом контексте. Результат тот же самый, если бы его никто не прерывал, а просто в соседнем ядре процессора работал второй поток. Прервётся текущий поток в ядре ЦПУ для выполнения другого потока, или оба потока будут выполняться одновременно - это не известно, и принимать на основе этого решения можно только в случае эксклюзивного доступа к железу и полному контролю надо процессором.
Основная проблема в том, как работают процессор и память. А работают они в 3 этапа: прочитать, вычислить, записать. Именно из-за этого и не получается без бубна/мьютексов/хитрых-алгоритмов атомарно выполнить инкремент ячейки памяти на многоядерных процессорах.
Только в потоке это будет строка кода, которая может быть прервана в любом месте.
Проблемы мультипотока не из-за то, что что-то прервывает выполнение потока. Как раз скорее наоборот - потому что потоки ничто не прерывает, когда они пытаются работать с общей памятью.
Получается в вашем случае действия являются атомарными? Наверное это обеспечивается использованием мьютексов. Только вот как понять какой именно мьютекс надо использовать? Одно дело когда мы пытаемся одно и то же действие выполнить параллельно в два потока - можно просто запретить это мьютексами для этого конкретного действия. Но если два разных действия используют общую память? ВКПа как-то отслеживает наличие обращений к общей памяти из разных "действий" и втыкает куда надо мьютексы? Или может в ВКПа вообще нет понятия "общая память"? Каждое действие работает со своей локальной памятью, а "общаются" между собой они через "обмен сообщениями"?
Вот вы опять пишете про какую-то модель параллельных вычислений которая, как я понял, скрывает от разработчика наличие реальных параллельных процессов на физическом уровне. Но что это такое? Мой Гугл про это ничего не знает. Как я понял, в небольших кусках кода, можно применять что-то вроде ярусно-параллельной формы записи алгоритма для автоматизированного поиска в коде тех мест, которые можно распараллелить. Такое можно в теории использовать в компиляторах и процессорах.
И я по прежнему не понимаю какой результат получится у вас, если вы не хотите (не видите пользы) использовать физическое распараллеливание в процессорах. Ваше решение по прежнему будет однопоточное, даже если оно будет моделировать параллельность. Это будет всего лишь модель, которая с некоторой степенью приближения будет работать так же как реальная система. Для того что бы от модели перейти на реальное физическое распараллеливание вам надо будет использовать потоки и процессы операционной системы.
Давайте на реальном примере. Как ваше решение будет "скрывать" наличие где-то в ядре потоков при инкременте общего счётчика? Разработчик, использующий ваше решение, при этом не "профессор". Он в общем случае просто напишет в своём коде на C/C++ *x += 1; Что помешает ему это сделать?
И про дискретность возникают вопросики. Это конечно удобный с точки зрения моделирования подход, считать что все задачки (или их части) выполняются условно моментально в интервалах между тактами системы. Но как этого добиться на практике? Если какие-то задачи будут не укладываться в такт, то придётся уменьшать частоту. Но тогда "потоки", которые выполняют быстрые задачи, будут простаивать в пустую. Такое ещё работает на очень низком уровне, где у нас "задачи" представляют отдельные инструкции CPU. Но как на высоком уровне добиться максимального использования процессорного времени при таком дискретном подходе к выполнению сложных алгоритмов?
Почитал про ярусно-параллельную форму. Пишут что это инструмент анализа алгоритмов для выявления участков, которые могут выполняться параллельно в разных процессах и потоках. Т.е. это просто форма записи алгоритма на которой лучше видно где мы можем воспользоваться распараллеливанием (тем самым, структурным).
Про сети Петри пишут, что это способ моделирования и формального описания параллельных процессов, в том числе и тех которые происходят при параллельном выполнении алгоритма на процессах и потоках. Даже в примерах по использованию сетей Петри приводятся классические задачи возникающие при реализации программ выполняющихся в несколько потоков/процессов. Как правило все эти задачи сводятся к тому как организовать работу с общими данными.
Никаких других определений "параллельные вычисления" мой "пузырь" в Гугле не приводит. Только про выполнение программ в параллельных процессах, потоках. Или про специфические инструкций процессора, которые позволяют проводить вычисления сразу над пачкой однотипных данных (SIMD инструкции). Но реализация этих инструкций такова, что их использование в рамках одного потока не создаёт всех тех проблем, которые свойственны параллельным программам.
Я так понимаю что ваше однопоточное решение - это не более чем модель реальных параллельных процессов. И в такой модели надо прям специально приложить усилия, что бы воспроизвести проблемы многопоточных приложений. Т.е. надо уже знать где возникают проблемы и описать их в вашей "модели". А если этого не знать, то никакой проблемы не возникнет в принципе, т.к. однопоточная реализация не может их воспроизвести.
Например проблема со счётчиком, с которым работают несколько потоков. В однопотоке надо специально сделать всё так, что бы разбить процесс инкремента на 3 части:
читаем значение счётчика из общей памяти куда-то себе во внутреннее состояние процесса;
прибавляем единицу к значению, которое хранится внутри процесса;
записываем значение из процесса обратно в общую память.
Только в таком варианте вы сможете в однопотоке модельно воспроизвести то, что может случится в мультипотоке. А если вы реализуете инкремент простым x += 1 то не заметите никаких проблем.
Ну и как итог, я по прежнему не очень понимаю что именно вы пытаетесь реализовать. Инструмент для моделирования параллельных процессов, для использования которого не надо быть "профессором", который из далека видит проблемные места в алгоритме? Или какую-то среду, которая выполняет эти самые параллельные процессы с реальным распараллеливанием без оглядки на то, знает программист про сопутствующие проблемы или нет?
В Qt так же как и везде, как минимум с появления Win32. Основной поток программы обрабатывает события от операционной системы (вернее от системы рабочего стола, но в винде эта штука встроенная). И если ваш "медленный" код не даёт выполняться этой обработке, то у вас "зависает" UI. Что бы такого не было, надо либо периодически прерывать свой код на вызов функции обработки событий. Либо выносить свой медленный код в отдельный поток.
Именно что свой код в отдельный поток, а не QT. Так будет проще.
Проектирование проектированием, а использовать имеющиеся в наличии "структурные" способы распараллеливания надо правильно и с умом.
Судя по всему ваше понимание того как должно выглядеть "параллельное программирование" не очень укладывается в то как работают распространённые операционные системы и компьютеры. А значит надо писать какой-то "транслятор", который будет конвертировать ваш "подход к проектированию", в код, который хорошо и быстро работает на имеющемся железе.
Если у вас в один поток сейчас всё правильно, то и в мультипоток можно сделать правильно. Если конечно не стремиться натянуть сову на глобус, делая это по заветам вашей параллельной модели. Надо просто оптимизировать ваш имеющийся код по классическим методикам, используя проверенные решения для обеспечения синхронизации или заданного порядка выполнения каких-то операций.
Про гарантированный порядок операций. Тут нужно либо сразу их оформлять как неделимую задачу. Либо нужен планировщик, который не будет такие операции раскидывать по разным потокам, а будет их выполнять в одном, последовательно. Ну и понятно, что надо максимально избегать обработки общих данных, которые могут быть изменены хотя бы в одном из потоков.
Само собой не будет работать подход в котором вы запускаете тысячи системных потоков. Они на это не рассчитаны. Вероятно вы слышали про "проблему 10к" - это как раз про это самое. Количество потоков, которые будут эффективно работать, ограничено числом ядер процессора. Следовательно системный поток должен выступать в роли универсального работяги, который получает задания и выполняет их, а не делает ровно одну задачу с контролируемой частотой, а в остальное время впустую проедает ресурсы.
С таким подходом можно получить выигрыш от структурного распараллеливания.
Ну да, сам wasm это скорее спецификация. Виртульной машиной наверное можно назвать какой-то wasmtime. Но в общем-то смысл же тот же, что и в jvm - компилим один раз в байткод и запускаем везде.
Даже ограничения похожие - нет прямого доступа к окружению, только через интерфейсы "рантайма"
Почему не подойдёт? Вроде тоже виртуальная машина с байткодом, как и WASM.
Так ведь есть уже для этого "взлетевшее" решение, JVM называется.
А вы пробовали для wasm делать вычисления в
f32
вместоf64
. Полагаю точности первого должно хватить для использования шума в играх.Кому просто обнаружить? Банки может и имеют такие возможности, и то не уверен что это проверяется через отправку SMS. Может мобильное приложение как-то может узнать ID симки или ещё как-то (на это маловероятно). А вот простые бизнесмены скорее всего пойдут лесом и не получат такой возможности.
Кроме того мы ведь говорим не про авторизацию по ID симки, а про ввод кода, который послали на номер телефона. Ничего кроме этого кода веб-сервис от пользователя не получит. А от сотовых операторов он получит только счёт на оплату SMS.
Поэтому без двухфакторной авторизации, только с одним OTP, полученном через SMS, лучше не рассчитывать на безопасность своих данных в сервисе. И про это скорее всего написано в оферте сервиса. Что-то вроде: "Если вы не удалили свой аккаунт перед тем как протерять свой номер телефона, то вы сам себе буратино, мы ни чего вам не гарантируем."
Бинго! И это прям красный флаг, который лучше не игнорить.
Если сервис использует только проверку по SMS, поддерживает номера любых операторов и хранит что-то личное, то лучше его не использовать.
Если сервис обслуживает клиентов только конкретного оператора, то у него есть возможность узнать о смене владельца номера. В этом случае чуть более надёжно получается. Если забыть про то, что sms в приципе не надёжны.
Если сервис просто показывает киношки и музыку, то эта проблема с авторизацией не так важна.
В этом контексте телега даже лучше получается. Можно получить user_id без необходимости договариваться с пачкой сотовых операторов, которые даже разговаривать с тобой не будут о такой интегарции.
Новый владелец номера может создать свой аккаунт телеги на этот номер. А потом пойти в сервис "МоиСамыеСекретныеДокументы.ком" и авторизоваться в нём используя код из телеги. И если этот сервис не проверит, что user_id, привязанный к номеру телефона, изменился, то новый владелец номера получит доступ к документам предыдущего владельца.
Телега сможет подтвердить только то, что у юзера в данный момент есть доступ к аккаунту с указанным номером телефона. То что номер телефона принадлежит этому человеку, телега гарантировать не может. Т.к. можно продолжать пользоваться авторизованным клиентом телеги до тех пор, пока новый владелец номера не решит создать свой аккаунт в телеге.
Вот если они предоставляют в том числе какой-то уникальный ID юзера, тогда это можно будет использовать для авторизации в сервисах, которые хранят персональные данные и/или личный контент пользователей.
Спасибо за инструкцию. Сделал у себя в AX3 по аналогии связку:
hev-socks5-tunnel -> Socks5-XRay ----> XRay Server
До этого использовал "порт-мапинг" для проброса WireGuard:
WG -> dokodemo-door-XRay ----> XRay Server -> WG
Но это работало очень медленно - 62 Мбит/с на скачивание при ширине канала 700 Мбит/сек. Почему так - не понятно. CPU роутера, можно сказать, был не нагружен.
Теперь, через
hev-socks5-tunnel
, у меня разгоняется до 230Мбит/сек, при общей нагрузке на CPU 50-60%.Это конечно сильно лучше чем было с WG, но не идеально. Если напрямую, в обход tun2socks, подключится браузером через Sock5 к XRay, то выдаёт 600 Мбит/сек.
Судя по распределению нагрузки на ядра роутера,
hev-socks5-tunnel
работает как будто в один поток. Только одно ядро из 4-её грузит на 100%, а остальные болтаются в районе 30-50%.Так же пробовал вариант с использованием WireGuard inbound-а в XRay, но это тоже работало очень медленно. По моему даже хуже чем с порт-мапингом.
Для inbound-ов можно прописать только порт. По дефолту оно будет слушать на всех интерфейсах контейнера. Не придётся менять конфиг xray при изменении IP адреса контейнера.
Всё дело в последней букве в названии библиотеки.
Ну да, механизм вытесняющей многозадачности, скорее всего сложно сделать без аппаратных прерываний. Иначе, как в современных асинхронных фреймворках, можно сделать кооперативную многозадачность - тут можно и без использования прерываний обойтись.
Прерывание выполнение потока не важно в этом контексте. Результат тот же самый, если бы его никто не прерывал, а просто в соседнем ядре процессора работал второй поток.
Прервётся текущий поток в ядре ЦПУ для выполнения другого потока, или оба потока будут выполняться одновременно - это не известно, и принимать на основе этого решения можно только в случае эксклюзивного доступа к железу и полному контролю надо процессором.
Основная проблема в том, как работают процессор и память. А работают они в 3 этапа: прочитать, вычислить, записать. Именно из-за этого и не получается без бубна/мьютексов/хитрых-алгоритмов атомарно выполнить инкремент ячейки памяти на многоядерных процессорах.
Как это "я не знаю как реализовано ядро ВКПа"? Это разве не ваше детище?
Глянул статью с описанием того как работать в ВКПа. Не нашёл ссылку на исходники.
Проблемы мультипотока не из-за то, что что-то прервывает выполнение потока. Как раз скорее наоборот - потому что потоки ничто не прерывает, когда они пытаются работать с общей памятью.
Получается в вашем случае действия являются атомарными? Наверное это обеспечивается использованием мьютексов. Только вот как понять какой именно мьютекс надо использовать? Одно дело когда мы пытаемся одно и то же действие выполнить параллельно в два потока - можно просто запретить это мьютексами для этого конкретного действия.
Но если два разных действия используют общую память? ВКПа как-то отслеживает наличие обращений к общей памяти из разных "действий" и втыкает куда надо мьютексы? Или может в ВКПа вообще нет понятия "общая память"? Каждое действие работает со своей локальной памятью, а "общаются" между собой они через "обмен сообщениями"?
Вот вы опять пишете про какую-то модель параллельных вычислений которая, как я понял, скрывает от разработчика наличие реальных параллельных процессов на физическом уровне. Но что это такое? Мой Гугл про это ничего не знает.
Как я понял, в небольших кусках кода, можно применять что-то вроде ярусно-параллельной формы записи алгоритма для автоматизированного поиска в коде тех мест, которые можно распараллелить. Такое можно в теории использовать в компиляторах и процессорах.
И я по прежнему не понимаю какой результат получится у вас, если вы не хотите (не видите пользы) использовать физическое распараллеливание в процессорах. Ваше решение по прежнему будет однопоточное, даже если оно будет моделировать параллельность. Это будет всего лишь модель, которая с некоторой степенью приближения будет работать так же как реальная система.
Для того что бы от модели перейти на реальное физическое распараллеливание вам надо будет использовать потоки и процессы операционной системы.
Давайте на реальном примере. Как ваше решение будет "скрывать" наличие где-то в ядре потоков при инкременте общего счётчика? Разработчик, использующий ваше решение, при этом не "профессор". Он в общем случае просто напишет в своём коде на C/C++
*x += 1;
Что помешает ему это сделать?
И про дискретность возникают вопросики. Это конечно удобный с точки зрения моделирования подход, считать что все задачки (или их части) выполняются условно моментально в интервалах между тактами системы. Но как этого добиться на практике?
Если какие-то задачи будут не укладываться в такт, то придётся уменьшать частоту. Но тогда "потоки", которые выполняют быстрые задачи, будут простаивать в пустую.
Такое ещё работает на очень низком уровне, где у нас "задачи" представляют отдельные инструкции CPU. Но как на высоком уровне добиться максимального использования процессорного времени при таком дискретном подходе к выполнению сложных алгоритмов?
Почитал про ярусно-параллельную форму. Пишут что это инструмент анализа алгоритмов для выявления участков, которые могут выполняться параллельно в разных процессах и потоках. Т.е. это просто форма записи алгоритма на которой лучше видно где мы можем воспользоваться распараллеливанием (тем самым, структурным).
Про сети Петри пишут, что это способ моделирования и формального описания параллельных процессов, в том числе и тех которые происходят при параллельном выполнении алгоритма на процессах и потоках. Даже в примерах по использованию сетей Петри приводятся классические задачи возникающие при реализации программ выполняющихся в несколько потоков/процессов. Как правило все эти задачи сводятся к тому как организовать работу с общими данными.
Никаких других определений "параллельные вычисления" мой "пузырь" в Гугле не приводит. Только про выполнение программ в параллельных процессах, потоках. Или про специфические инструкций процессора, которые позволяют проводить вычисления сразу над пачкой однотипных данных (SIMD инструкции). Но реализация этих инструкций такова, что их использование в рамках одного потока не создаёт всех тех проблем, которые свойственны параллельным программам.
Я так понимаю что ваше однопоточное решение - это не более чем модель реальных параллельных процессов. И в такой модели надо прям специально приложить усилия, что бы воспроизвести проблемы многопоточных приложений. Т.е. надо уже знать где возникают проблемы и описать их в вашей "модели". А если этого не знать, то никакой проблемы не возникнет в принципе, т.к. однопоточная реализация не может их воспроизвести.
Например проблема со счётчиком, с которым работают несколько потоков. В однопотоке надо специально сделать всё так, что бы разбить процесс инкремента на 3 части:
читаем значение счётчика из общей памяти куда-то себе во внутреннее состояние процесса;
прибавляем единицу к значению, которое хранится внутри процесса;
записываем значение из процесса обратно в общую память.
Только в таком варианте вы сможете в однопотоке модельно воспроизвести то, что может случится в мультипотоке. А если вы реализуете инкремент простым
x += 1
то не заметите никаких проблем.
Ну и как итог, я по прежнему не очень понимаю что именно вы пытаетесь реализовать. Инструмент для моделирования параллельных процессов, для использования которого не надо быть "профессором", который из далека видит проблемные места в алгоритме? Или какую-то среду, которая выполняет эти самые параллельные процессы с реальным распараллеливанием без оглядки на то, знает программист про сопутствующие проблемы или нет?
В Qt так же как и везде, как минимум с появления Win32. Основной поток программы обрабатывает события от операционной системы (вернее от системы рабочего стола, но в винде эта штука встроенная). И если ваш "медленный" код не даёт выполняться этой обработке, то у вас "зависает" UI.
Что бы такого не было, надо либо периодически прерывать свой код на вызов функции обработки событий. Либо выносить свой медленный код в отдельный поток.
Именно что свой код в отдельный поток, а не QT. Так будет проще.
Проектирование проектированием, а использовать имеющиеся в наличии "структурные" способы распараллеливания надо правильно и с умом.
Судя по всему ваше понимание того как должно выглядеть "параллельное программирование" не очень укладывается в то как работают распространённые операционные системы и компьютеры. А значит надо писать какой-то "транслятор", который будет конвертировать ваш "подход к проектированию", в код, который хорошо и быстро работает на имеющемся железе.
Если у вас в один поток сейчас всё правильно, то и в мультипоток можно сделать правильно. Если конечно не стремиться натянуть сову на глобус, делая это по заветам вашей параллельной модели. Надо просто оптимизировать ваш имеющийся код по классическим методикам, используя проверенные решения для обеспечения синхронизации или заданного порядка выполнения каких-то операций.
Про гарантированный порядок операций. Тут нужно либо сразу их оформлять как неделимую задачу. Либо нужен планировщик, который не будет такие операции раскидывать по разным потокам, а будет их выполнять в одном, последовательно. Ну и понятно, что надо максимально избегать обработки общих данных, которые могут быть изменены хотя бы в одном из потоков.
Само собой не будет работать подход в котором вы запускаете тысячи системных потоков. Они на это не рассчитаны. Вероятно вы слышали про "проблему 10к" - это как раз про это самое. Количество потоков, которые будут эффективно работать, ограничено числом ядер процессора. Следовательно системный поток должен выступать в роли универсального работяги, который получает задания и выполняет их, а не делает ровно одну задачу с контролируемой частотой, а в остальное время впустую проедает ресурсы.
С таким подходом можно получить выигрыш от структурного распараллеливания.