Pull to refresh
3
0
Send message

Ну да, механизм вытесняющей многозадачности, скорее всего сложно сделать без аппаратных прерываний. Иначе, как в современных асинхронных фреймворках, можно сделать кооперативную многозадачность - тут можно и без использования прерываний обойтись.

Прерывание выполнение потока не важно в этом контексте. Результат тот же самый, если бы его никто не прерывал, а просто в соседнем ядре процессора работал второй поток.
Прервётся текущий поток в ядре ЦПУ для выполнения другого потока, или оба потока будут выполняться одновременно - это не известно, и принимать на основе этого решения можно только в случае эксклюзивного доступа к железу и полному контролю надо процессором.

Основная проблема в том, как работают процессор и память. А работают они в 3 этапа: прочитать, вычислить, записать. Именно из-за этого и не получается без бубна/мьютексов/хитрых-алгоритмов атомарно выполнить инкремент ячейки памяти на многоядерных процессорах.

Как это "я не знаю как реализовано ядро ВКПа"? Это разве не ваше детище?

Глянул статью с описанием того как работать в ВКПа. Не нашёл ссылку на исходники.

Только в потоке это будет строка кода, которая может быть прервана в любом месте.

Проблемы мультипотока не из-за то, что что-то прервывает выполнение потока. Как раз скорее наоборот - потому что потоки ничто не прерывает, когда они пытаются работать с общей памятью.

Получается в вашем случае действия являются атомарными? Наверное это обеспечивается использованием мьютексов. Только вот как понять какой именно мьютекс надо использовать? Одно дело когда мы пытаемся одно и то же действие выполнить параллельно в два потока - можно просто запретить это мьютексами для этого конкретного действия.
Но если два разных действия используют общую память? ВКПа как-то отслеживает наличие обращений к общей памяти из разных "действий" и втыкает куда надо мьютексы? Или может в ВКПа вообще нет понятия "общая память"? Каждое действие работает со своей локальной памятью, а "общаются" между собой они через "обмен сообщениями"?

Вот вы опять пишете про какую-то модель параллельных вычислений которая, как я понял, скрывает от разработчика наличие реальных параллельных процессов на физическом уровне. Но что это такое? Мой Гугл про это ничего не знает.
Как я понял, в небольших кусках кода, можно применять что-то вроде ярусно-параллельной формы записи алгоритма для автоматизированного поиска в коде тех мест, которые можно распараллелить. Такое можно в теории использовать в компиляторах и процессорах.

И я по прежнему не понимаю какой результат получится у вас, если вы не хотите (не видите пользы) использовать физическое распараллеливание в процессорах. Ваше решение по прежнему будет однопоточное, даже если оно будет моделировать параллельность. Это будет всего лишь модель, которая с некоторой степенью приближения будет работать так же как реальная система.
Для того что бы от модели перейти на реальное физическое распараллеливание вам надо будет использовать потоки и процессы операционной системы.

Давайте на реальном примере. Как ваше решение будет "скрывать" наличие где-то в ядре потоков при инкременте общего счётчика? Разработчик, использующий ваше решение, при этом не "профессор". Он в общем случае просто напишет в своём коде на C/C++
*x += 1;
Что помешает ему это сделать?

И про дискретность возникают вопросики. Это конечно удобный с точки зрения моделирования подход, считать что все задачки (или их части) выполняются условно моментально в интервалах между тактами системы. Но как этого добиться на практике?
Если какие-то задачи будут не укладываться в такт, то придётся уменьшать частоту. Но тогда "потоки", которые выполняют быстрые задачи, будут простаивать в пустую.
Такое ещё работает на очень низком уровне, где у нас "задачи" представляют отдельные инструкции CPU. Но как на высоком уровне добиться максимального использования процессорного времени при таком дискретном подходе к выполнению сложных алгоритмов?

Почитал про ярусно-параллельную форму. Пишут что это инструмент анализа алгоритмов для выявления участков, которые могут выполняться параллельно в разных процессах и потоках. Т.е. это просто форма записи алгоритма на которой лучше видно где мы можем воспользоваться распараллеливанием (тем самым, структурным).

Про сети Петри пишут, что это способ моделирования и формального описания параллельных процессов, в том числе и тех которые происходят при параллельном выполнении алгоритма на процессах и потоках. Даже в примерах по использованию сетей Петри приводятся классические задачи возникающие при реализации программ выполняющихся в несколько потоков/процессов. Как правило все эти задачи сводятся к тому как организовать работу с общими данными.

Никаких других определений "параллельные вычисления" мой "пузырь" в Гугле не приводит. Только про выполнение программ в параллельных процессах, потоках. Или про специфические инструкций процессора, которые позволяют проводить вычисления сразу над пачкой однотипных данных (SIMD инструкции). Но реализация этих инструкций такова, что их использование в рамках одного потока не создаёт всех тех проблем, которые свойственны параллельным программам.

Я так понимаю что ваше однопоточное решение - это не более чем модель реальных параллельных процессов. И в такой модели надо прям специально приложить усилия, что бы воспроизвести проблемы многопоточных приложений. Т.е. надо уже знать где возникают проблемы и описать их в вашей "модели". А если этого не знать, то никакой проблемы не возникнет в принципе, т.к. однопоточная реализация не может их воспроизвести.

Например проблема со счётчиком, с которым работают несколько потоков. В однопотоке надо специально сделать всё так, что бы разбить процесс инкремента на 3 части:

  • читаем значение счётчика из общей памяти куда-то себе во внутреннее состояние процесса;

  • прибавляем единицу к значению, которое хранится внутри процесса;

  • записываем значение из процесса обратно в общую память.

Только в таком варианте вы сможете в однопотоке модельно воспроизвести то, что может случится в мультипотоке. А если вы реализуете инкремент простым
x += 1
то не заметите никаких проблем.

Ну и как итог, я по прежнему не очень понимаю что именно вы пытаетесь реализовать. Инструмент для моделирования параллельных процессов, для использования которого не надо быть "профессором", который из далека видит проблемные места в алгоритме? Или какую-то среду, которая выполняет эти самые параллельные процессы с реальным распараллеливанием без оглядки на то, знает программист про сопутствующие проблемы или нет?

В Qt так же как и везде, как минимум с появления Win32. Основной поток программы обрабатывает события от операционной системы (вернее от системы рабочего стола, но в винде эта штука встроенная). И если ваш "медленный" код не даёт выполняться этой обработке, то у вас "зависает" UI.
Что бы такого не было, надо либо периодически прерывать свой код на вызов функции обработки событий. Либо выносить свой медленный код в отдельный поток.

Именно что свой код в отдельный поток, а не QT. Так будет проще.

Проектирование проектированием, а использовать имеющиеся в наличии "структурные" способы распараллеливания надо правильно и с умом.

Судя по всему ваше понимание того как должно выглядеть "параллельное программирование" не очень укладывается в то как работают распространённые операционные системы и компьютеры. А значит надо писать какой-то "транслятор", который будет конвертировать ваш "подход к проектированию", в код, который хорошо и быстро работает на имеющемся железе.

Если у вас в один поток сейчас всё правильно, то и в мультипоток можно сделать правильно. Если конечно не стремиться натянуть сову на глобус, делая это по заветам вашей параллельной модели. Надо просто оптимизировать ваш имеющийся код по классическим методикам, используя проверенные решения для обеспечения синхронизации или заданного порядка выполнения каких-то операций.

Про гарантированный порядок операций. Тут нужно либо сразу их оформлять как неделимую задачу. Либо нужен планировщик, который не будет такие операции раскидывать по разным потокам, а будет их выполнять в одном, последовательно. Ну и понятно, что надо максимально избегать обработки общих данных, которые могут быть изменены хотя бы в одном из потоков.

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

С таким подходом можно получить выигрыш от структурного распараллеливания.

Получается у вас научно-аналитический интерес? Т.е. не выполнять какую-то задачу быстро за счёт распараллеливания, а реализовать модель чего-то из "реального мира". И главное что бы она выдавала результат правильный, а скорость - второе дело.

Вроде вы назвали две параллельные модели, но тут же говорите что их нет, но при этом у вас в ВПКа оно как-то реализовано. :-)

Кстати, что такое ВПКа?

Не понятна ваша конечная цель. Вы хотите придумать язык программирования или фреймворк, который реализует параллельную модель и запустит её на имеющихся в наличии структурных механизмах (мультиядерные процессоры с общей памятью)?

Но если модели якобы нет, то в чём смысл всего этого? Вот есть у нас в наличии структурные механизмы и вполне себе работающая "модель" - разделяй и властвуй. Бери большую задачу и разбивай её на маленькие, не пересекающиеся, и запускай их в разных потоках/процессах.

Что вы имеете ввиду под "параллельностью"? Одновременное выполнение? Если она у вас уже есть, тогда зачем вам потоки? А если, как я понял, у вас "автоматы в одном потоке", то нет у вас ни какой параллельности - у вас конкурентное выполнение (одновременно работает только один кусок кода).

Поводу того, что бы объединить "автоматы" и "потоки" - это вам прямой наводкой в современные асинхронные фреймворки. Они позволяют запускать "корутины" как в одном потоке, так и распределять их выполнение по разным потокам.
Не знаю на счёт таких фреймворков в C++ и как они дают гарантии, что не будет проблем с выполнением корутин в разных потоках (наверное ни как - программист должен сам за этим следить). Но как минимум в Rust есть фреймворк tokio и он за счёт особенностей языка позволяет на этапе компиляции предотвратить попытку запуска в другом потоке кода, с которым нельзя так делать (который не обеспечивает мультипоточной безопасности).

Синхронизация потоков возможна только относительная, всё равно, хотя бы очень мало, почти не заметно, но они будут работать в разнобой. Определённо на такую "синхронность" не стоит рассчитывать в критических задачах. Особенно если потоков много и у каждого из них есть свой собственный "флаг" с разрешением на работу. Последний поток будет отставать от первого как минимум на то время которое выполняется цикл для перебора всех потоков, что бы выставить им "флаг" в true. Ну или надо очень угадать с задержкой в usleep(), что бы потоки "просыпались" после того, когда все флаги уже проставлены.

"Параллельная" работа в одном потоке - это, как я понял, сарказм? :-)
В рамках одного потока не возможна параллельная работа. Параллельная в смысле одновременная. Можно только организовать конкурентную многозадачность тем или иным способом.
При использовании автоматов в одном потоке или их варианта, который называют асинхронными фреймворками (корутины и всё такое) очень легко контролировать отсутствие "одновременного" доступа к общему ресурсу. При этом не нужны будут медленные мьютексы.

И насчёт запуска тысячи потоков - это вы конечно, что называется, "психанули". Определённо на средне-статистическом 16-ядерном процессоре пользы от этого совершенно ни какой. Даже наоборот, если эти потоки будут со своими мьютексами конкурировать за процессор, то они будут ещё сильнее мешать тому единственному потоку, который делает работу.

Результат ваших изысканий был предсказуем и без реальных тестов. Одно дело, когда у вас один "работник" просыпается по будильнику, заходит в кабинет, быстро делает свою задачу и уходит. И совсем другое когда у вас десяток таких работников, и все они одновременно долбятся в одну дверь кабинета, толкаются и мешают друг другу.
Потоки не помогут для решения задачи, которую надо решать исключительно в одно "лицо". Если у вас именно такая задача и она одна - значит вам не нужны потоки. Если же у вас есть много задач, которые не мешают друг другу - потоки могут быть полезны.

Словил очередной диссонанс от вашей статьи. А в это раз ещё и от коментов к ней.
Ощущение что и статью и коменты писал ChatGPT.
Или может вы просто издеваетесь/прикалываетесь над читателями? Как можно заявлять о нескольких десятках лет опыта разработки программ и при этом выдавать такие наивные куски кода?

Листинг 3
Ваши потоки будет молотить воду в ступе нагружая ядро процессора пустым циклом, пока какой-то внешний "контроллер" не выставит bIfExecuteStep в true. Но это только на один прогон тела цикла, дальше опять будет бессмысленая пустая работа. Разве что вы укажете подходящую задержку для usleep, чтобы она примерно соответствовала частоте работы "контроллера", который разрешает потоку делать полезную работу.

Листинг 4
Поздравляю, вы доказали что 9 женщин не родят ребёнка за один месяц.
Все ваши тысячи потоков будут бессмысленно греть возух в ожидании снятия лока в мьютексе или семафоре. А полезную работу по прибавлению единицы к счётчику всегда будет делать в данный момент времени только один поток, который "захватил" лок.

Если ваши алгоритмы перестают нормально работать в потоках, то скорее всего проблема в том, что вы в этих потоках меняете слишком много общих данных. А попытка защитится от всяких race-ов с помощью мьютексов даёт ужасный результат, т.к. почти вся работа потока у вас закрыта мютексом. Это неправильный подход, если вы хотите ускорения от потоков. Мьютексы должны использоваться точечно и на очень короткое время по сравнению с временем, которое поток тратит на решение задачи.
Ваш код со счётчиком отличный пример того как не надо делать. В нём инкремент счётчика занимает 0% времени, а 99.(9)% занимает возня с мьютексами.

Вам бы без QT разобраться с тем как работают потоки и процессоры, а то больше похоже на то, что вы месяц воевали с UI фреймворком, а не с потоками.

Давно перешёл на новй UI. Из того что мне не понравилось в нём:

  • одинаковый цвет фона для кода и для колонки с номерами строк. Иногда не могу визуально понять где находится начало строки, если где-то за пределами видимой области есть брейкпоинты. Причём это не особенность темы, как я понял там в принципе используется для этого цвета одна и та же настройка, вместо двух отдельных.

  • не корректно работает кастомизация тулбаров. В настройке можно добавить кнопку, но на тулбаре она не будет отображаться. Например нельзя добавить кнопку "Show diff" в тулбар окна VCS (Git), которая там была в старом UI по умолчанию.

В статье формулировка не полная.

Доступ к приватным сущностям в расте есть из любого кода, который расположен в модуле не выше того, где определена приватная сущность.

При этом каким образом модули раскиданы по папкам и файлам - не имеет значение. Значение имеет только иерархия модулей.

А как заставить ноутбук автоматически включиться после продолжительного отсутствия электропитания, когда батарейка успела разрядится? В этом плане штуки вроде Raspberry выглядят надёжнее.

AX3 из коробки идут с 7-ой версией и с новой реализацией пакета для работы с WiFi (который в UI так и называется "WiFi" вместо старого "Wireless"). Поэтому на AX3 не должно быть вообще каких-то проблем, т.к. нет ни какой "миграции" при обновлении.

В вашем примере всё таки есть синхронизация серверов, хоть и медленная. Значит эту задачу можно решить с использованием грамотного UI на клиенте. Который сможет донести до юзера информацию, что его запрос всё ещё находится в обработке и надо подождать. Можно ведь рассчитать максимальное время, требуемое на синхронизацию серверов и сообщить клиенту в ответе на первый запрос, сколько времени надо что бы информация о состоянии задачи была достпна на всех серверах.

1
23 ...

Information

Rating
Does not participate
Location
Россия
Registered
Activity