Про варианты многопоточного взаимодействия...
От: Shmj Ниоткуда  
Дата: 18.10.23 21:24
Оценка:
1. Вот есть стандартное решение — типа как в С++. Вы запускаете поток и как бы просто исполнение раздвоилось. Теперь нужно помнить, что к одной и той же переменной могут одновременно получит доступ два разных потока — как-то синхронизировать эти доступы, учитывать это.

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

2. А ведь есть и иные решения — типа как в Dart. Доступ к переменным всегда из одного потока — нет возможности раздвоить как в C++. Т.е. ты можешь не беспокоиться о том, что кто-то левый изменит переменную и произойдет конфликт. 100% гарантия безопасности.

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

Подход 2 — не требует адаптации мозга и воспринимается интуитивно. Но тоже есть беда — некоторые вещи допустимы только из основного потока. В таком случае вам нужно делать некий спец. вызов — перегонку туда-обратно чисто из-за данной специфики

Какой подход вам кажется более удобным и почему?
Отредактировано 18.10.2023 21:24 Shmj . Предыдущая версия . Еще …
Отредактировано 18.10.2023 21:24 Shmj . Предыдущая версия .
Re: Про варианты многопоточного взаимодействия...
От: ononim  
Дата: 18.10.23 22:00
Оценка: +2
S>1. Вот есть стандартное решение — типа как в С++. Вы запускаете поток и как бы просто исполнение раздвоилось. Теперь нужно помнить, что к одной и той же переменной могут одновременно получит доступ два разных потока — как-то синхронизировать эти доступы, учитывать это.
Я бы не сказал что это 'как в С++'. Это скорее просто подход без абстракций, максимально близко к тому как это реализуется операционной системой.
А абстракции есть и для С++ — https://learn.microsoft.com/ru-ru/cpp/parallel/openmp/reference/openmp-directives?view=msvc-170 просто про них мало говорят
Как много веселых ребят, и все делают велосипед...
Re: Про варианты многопоточного взаимодействия...
От: Разраб  
Дата: 19.10.23 01:30
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Какой подход вам кажется более удобным и почему?

https://dlang.org/library/std/concurrency.html
обмен сообщениями т.к. решает все проблемы. в том числе когнитивные.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Про варианты многопоточного взаимодействия...
От: so5team https://stiffstream.com
Дата: 19.10.23 04:42
Оценка: +2
Здравствуйте, Shmj, Вы писали:

S>Какой подход вам кажется более удобным


Основанный на специфике и требованиях к задаче, имеющихся в наличии возможностях и здравом смысле.

S>и почему?


Потому что это работает.
Re: Про варианты многопоточного взаимодействия...
От: Skorodum Россия  
Дата: 19.10.23 07:14
Оценка:
Здравствуйте, Shmj, Вы писали:

S>1. Вот есть стандартное решение — типа как в С++. Вы запускаете поток и как бы просто исполнение раздвоилось. Теперь нужно помнить, что к одной и той же переменной могут одновременно получит доступ два разных потока — как-то синхронизировать эти доступы, учитывать это.

В плюсах по разному можно.
Вот недавно обсуждали
Автор: Skorodum
Дата: 10.10.23
, что можно жить вполне неплохо с многопоточностью и без явной синхронизации (точнее, полностью отдав синхронизацию библиотеке).
qt
Re: Про варианты многопоточного взаимодействия...
От: Вумудщзук Беларусь  
Дата: 19.10.23 07:28
Оценка:
S>Теперь нужно помнить, что к одной и той же переменной могут одновременно получит доступ два разных потока — как-то синхронизировать эти доступы, учитывать это.

S>Dart. Доступ к переменным всегда из одного потока — нет возможности раздвоить как в C++. Т.е. ты можешь не беспокоиться о том, что кто-то левый изменит переменную и произойдет конфликт. 100% гарантия безопасности.


если нет в явном виде необходимости заботиться о "синхронизации этих доступов", это ещё не значит, что это не происходит где-то под капотом. А тогда какая разница между этими подходами? Только в том, что в одном ты ручками организуешь доступ, а в другом это делает за тебя либа/среда? Так это типовая разница между "высокоуровневым" и "низкоуровневым". В одном случае больше возможностей ценой возможных ошибок, в другом больше комфорта ценой возможно меньшей производительности и всяческих ограничений.
Re: Про варианты многопоточного взаимодействия...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.10.23 07:37
Оценка: +4
Здравствуйте, Shmj, Вы писали:

S>Какой подход вам кажется более удобным и почему?


Вообще странный вопрос.
Три подхода к конкурентной работе есть:
1) Атомарность и lock-free алгоритмы на её базе. Минимальные затраты и максимальные "приседания".
2) Блокировки общих данных. Потенциальные взаимоблокировки при низкой гранулярнсти и системные вызовы для остановки потока
3) Message passing — самый простой с точки зрения разработчика, но требуются хорошие библиотеки и средства языка. А также message passing это копироване данных, что не всегда приемлемо.

Нет подхода который однозначно лучше или хуже, все зависит от конкретной задачи.
ИМХО языки должны позволять все три.
Re[2]: Про варианты многопоточного взаимодействия...
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.10.23 11:52
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>>Какой подход вам кажется более удобным и почему?


G>Вообще странный вопрос.

G>Три подхода к конкурентной работе есть:
G>1) Атомарность и lock-free алгоритмы на её базе. Минимальные затраты и максимальные "приседания".
G>2) Блокировки общих данных. Потенциальные взаимоблокировки при низкой гранулярнсти и системные вызовы для остановки потока
G>3) Message passing — самый простой с точки зрения разработчика, но требуются хорошие библиотеки и средства языка. А также message passing это копироване данных, что не всегда приемлемо.

G>Нет подхода который однозначно лучше или хуже, все зависит от конкретной задачи.

G>ИМХО языки должны позволять все три.

Ну еще есть ThreadLocal
и AsyncLocal
и солнце б утром не вставало, когда бы не было меня
Re[3]: Про варианты многопоточного взаимодействия...
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.10.23 13:18
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Ну еще есть ThreadLocal

S>и AsyncLocal

Они решают ровно обратную задачу — чтобы потоки НЕ взаимодействовали.
Re: Про варианты многопоточного взаимодействия...
От: Alekzander  
Дата: 19.10.23 13:29
Оценка:
Здравствуйте, Shmj, Вы писали:

S>2. А ведь есть и иные решения — типа как в Dart. Доступ к переменным всегда из одного потока — нет возможности раздвоить как в C++. Т.е. ты можешь не беспокоиться о том, что кто-то левый изменит переменную и произойдет конфликт. 100% гарантия безопасности.


Память фундаментально устроена так, что доступ из разных потоков надо искусственно ограничивать. И либо это будут ненадёжные и легко обходимые ограничения, либо перфоманс пострадает. Чудес ведь не бывает.
Отредактировано 19.10.2023 13:29 Alekzander . Предыдущая версия .
Re[4]: Про варианты многопоточного взаимодействия...
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.10.23 13:36
Оценка:
Здравствуйте, gandjustas, Вы писали:

S>> Ну еще есть ThreadLocal

S>>и AsyncLocal

G>Они решают ровно обратную задачу — чтобы потоки НЕ взаимодействовали.



Ну это один из способов синхронизации, когда данные должны быть привязаны к потоку или задаче. Часто нужно прокинуть данные по потоку не в переменных методов, а просто в данных потока.
А так придется городить какую то хэш таблицу с привязкой данных к Id потоку, удалять по завершении и тд. И при этом удалять данные из словаря нужно синхронизировать.
Это всевозможные HTTPContex итд

Один из способ уменьшить конкуренцию. Кстати словарь проще разделить на n-словарей
Доступ к каждому через HashCode % n. Так мы уменьшим конкуренцию в n раз.
и солнце б утром не вставало, когда бы не было меня
Re: Про варианты многопоточного взаимодействия...
От: Sm0ke Россия ksi
Дата: 19.10.23 13:39
Оценка:
Здравствуйте, Shmj

В каких случаях происходит (data race) гонка?

* Когда один поток пишет в ту же ячейку, откуда другой в то-же время читает
Верно?

* Когда оба пишут в одну ячейку
Верно?

* А будет ли гонка, когда все только читают?
С железом, где это причина для гонки, то наверно лучше копировать для каждого thread

--

С точки зрения статиков.

Разделим статики на две группы:
1: readonly
2: mutable

1) Если взять только readonly статики, и дать к ним доступ из разных потоков без синхронизации, то будет ли data race?
Тут есть нюанс. Насколько readonly есть deep ?
Скажем есть const obj, а в нём mutable .prop — то как быть?
Для const-full-depth вроде понятно.

2) подРазвилка для mutable:

2.а)
скопировать mutable статики до запуска каждого нового thread
плюсы: быстрее к ним доступ, проще код, отсутсвтие deadlock -ов
минусы: занимает больше памяти; рассинхрон по значением после изменений; время будет потрачено на копирование;

2.б)
Отдельный thread работает с mutable статиками через сообщения
Механизм сообщений между потоками мне неизвестен.
Сколько байт можно передать?
Нужно ли знать все типы хранимых данных?

2.б.Х) А если сама структура типа является mutable прямо в run-time? -- Как быть с другими потоками, которые работают с mutable типом?
По идее в значении хранить указатель на версию _текущего_ типа // для readonly типа — можно и не хранить
При динамиеском изменении структуры типа — делать COW типа. Так уже имеющиеся значения не потеряют целостность.
Вроде бы не должны... (привет, методы)

А новые значения по новой версии типа — сравнимы ли со старыми?

--

Какой подход вам кажется более удобным и почему?

Предполагаемый ответ:
Если не отказываться от mutable статиков, то желательно иметь возможность задать способ хранения и доступа в каждом конкретном случае явно.

p/s: Какие ещё способы можно найти, кроме этих двух?
Отредактировано 19.10.2023 13:54 Sm0ke (ps) . Предыдущая версия . Еще …
Отредактировано 19.10.2023 13:44 Sm0ke . Предыдущая версия .
Re: Про варианты многопоточного взаимодействия..
От: Sm0ke Россия ksi
Дата: 19.10.23 13:52
Оценка:
А можно ли эту задачу решить на уровне железа?
Спроектировать такую архетектуру, в которой не будет проблемы data race вообще?

Просто будет RW память, которой всё равно не кол-во запущенных threads
Re[2]: Про варианты многопоточного взаимодействия..
От: Pzz Россия https://github.com/alexpevzner
Дата: 19.10.23 21:02
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>А можно ли эту задачу решить на уровне железа?

S>Спроектировать такую архетектуру, в которой не будет проблемы data race вообще?

Ну например, можно собрать машинку из N самостоятельных машинок, на каждой из которых исполняется ровно один поток, и которые общаются сообщениями по какой-нибудь аппаратной шине, напоминающей сеть.
Re[2]: Про варианты многопоточного взаимодействия..
От: ononim  
Дата: 19.10.23 21:11
Оценка:
S>А можно ли эту задачу решить на уровне железа?
S>Спроектировать такую архетектуру, в которой не будет проблемы data race вообще?
S>Просто будет RW память, которой всё равно не кол-во запущенных threads
Так памяти то вобщемто и так все равно с большего
Как много веселых ребят, и все делают велосипед...
Re[5]: Про варианты многопоточного взаимодействия...
От: AleksandrN Россия  
Дата: 19.10.23 22:38
Оценка:
Здравствуйте, Serginio1, Вы писали:

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


Можно не делать самому, а использовать средства ОС — Thread Local Storage в Windows или thread key в UNIX.

Но лучше использовать средства языка, если такая возможность там предусмотрена.
Отредактировано 19.10.2023 22:44 AleksandrN . Предыдущая версия .
Re[6]: Про варианты многопоточного взаимодействия...
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 20.10.23 07:52
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN>Здравствуйте, Serginio1, Вы писали:


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


AN>Можно не делать самому, а использовать средства ОС — Thread Local Storage в Windows или thread key в UNIX.


AN>Но лучше использовать средства языка, если такая возможность там предусмотрена.


Речь как раз шла про
S>> Ну еще есть ThreadLocal
S>>и AsyncLocal
и солнце б утром не вставало, когда бы не было меня
Re[2]: Про варианты многопоточного взаимодействия..
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.10.23 19:59
Оценка:
Здравствуйте, Sm0ke, Вы писали:

S>Спроектировать такую архетектуру, в которой не будет проблемы data race вообще?

Видеокарты
Sic luceat lux!
Re[3]: Про варианты многопоточного взаимодействия..
От: reversecode google
Дата: 20.10.23 20:14
Оценка:
смутно помню в SYCL data race вроде бы есть
могу конечно ошибаться
для общего образования слушал несколько лет назад пару лекций
Re: Про варианты многопоточного взаимодействия...
От: _ilya_  
Дата: 21.10.23 00:07
Оценка:
Здравствуйте, Shmj, Вы писали:
S>Доступ к переменным всегда из одного потока — нет возможности раздвоить как в C++. Т.е. ты можешь не беспокоиться о том, что кто-то левый изменит переменную и произойдет конфликт. 100% гарантия безопасности.

А теперь возьми задачу, которая требует максимальной производительности... САУ, сводится к перемножению матриц. Это в чем суперкомпьютеры состязаются по производительнсти. Перемножение матриц это туча операций и записи конкурирующих потоков в одну ячейку, это скорее уже изученный этап, но оптиимзаци там будет до бесконечности.

Вроде как просто — перемножить матрицы, но когда у тебя N ядер, и еще скорость зависит от обращений в память, а это зависит от данных в кеш — в итоге будет чет нетривиальное (Intel® Math Kernel Library (Intel® MKL)). И даже на копеечных древних процессорах крайне близко к 1 TFLOPS (800 GFLOPS выдает один Xeon 2696v4 — можете свои процы затестить — версия древняя, но все еще рабочая AVX2 https://github.com/sanekgusev/LinX-old/releases/tag/0.6.5, но такие процессоры стаятся парой и запросто преодолевают рубеж в 1 TFLOPS). Хочешь многопоток, много процов и дичайшую производительность ну чуть хуже ThreadRipper, Китайцы распродают по запчастям свои устаревшие суперкомпьютеры. ЭЭЭ, 18 ядерный 2696v3 стоит 4тыс. руб? и он ставится парой, и тогда будет дикое > 1 TFLOPS.

Современные десктоп процы (i9) уже тоже перешагнули за 1 TFLOPS, ну а суперкомпьютеры там на PFLOPS идут.
Ествественно там вся логика рассчитана, а не только многопоток, все нюансы — как кэш работает. В реальных математических задачах показать производительность примерно равную теоретически заложенной в железке — тупо количество ядер помножить на чатоту и число операций за такт. Если это сходится с заявленным для процессора и такие вычислительные мощности подтверждаются на практике — это радует, что процессор как заявленно работает и софт максимально опимально написан (увы, кто пишет софт сейчас скорее могут быть полные неучи в многопроцессорорных задачах, вплоть не понимают что разные потоки с разной скоростью выполняться могут и не имеют понятия, что при стыке двух потоков будут проблемы).
Отредактировано 21.10.2023 0:52 _ilya_ . Предыдущая версия . Еще …
Отредактировано 21.10.2023 0:46 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:41 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:41 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:37 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:37 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:33 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:22 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:20 _ilya_ . Предыдущая версия .
Отредактировано 21.10.2023 0:14 _ilya_ . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.