[ Главная · Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 10 из 10
  • «
  • 1
  • 2
  • 8
  • 9
  • 10
Пытаюсь замутить свой симулятор.
V9Дата: Пятница, 07.06.2024, 13:26 | Сообщение # 181
Поездной диспетчер
Группа: Пользователи
Сообщений: 355
Награды: 8
Репутация: 0
Статус: Offline
Цитата V9 ()
Есть у меня психологическая проблема. Я сам себе ставлю некие задачи повышенной сложности которые сам же потом не могу решить. Из-за чего общий прогресс замедляется или стоит на месте. Надеюсь, я смогу это побороть в себе.


Встрял на проблеме "параллельной работы двух потоков - Модели и Графики - и передачи данных между ними без задержек".

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

Добавлено (10.06.2024, 12:51)
---------------------------------------------
В негативном ахрене от Java.

Суть. Обработка(программа) в DSim идет в два потока:

1. Поток №1 постоянно читает данные из GID.txt, разбирает их и должен отправить в поток №2. сигнализирует потоку №2 о поступлении новых данных.
2. Поток №2 занят отрисовкой графики на экране. Он вызывается (косвенно) из потока №1, а так же из операционки, если надо обновить окно (скажем, была другая прога над моим окном, убралась,надо отрисовать наше окно) или же как следствие действий пользователя. Скажем, пользователь изменил размеры, подвигал по окну мышкой, нажал клавиши и т.п.

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

Поэтому я ставил сам себе задачу написать передачу данных "без блокировок".
1. не должны использоваться мьютексы (mutex) - https://ru.wikipedia.org/wiki/%D0%9C%D1%8C%D1%8E%D1%82%D0%B5%D0%BA%D1%81
2. не должны использоваться volatile переменные, которые вызывают "атомарные операции" - https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%BE%D0%BC%D0%B0%D1%80%D0%BD%D0%B0%D1%8F_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F
3. Какой бы большой пакет данных не пришел, он должен быть передан "за один цикл".
4. Прога должна минимизировать "удаление устаревших аднных", данные должны правиться, а не удаляться. Это означает, что требуется еще и передача "использованных данных" обратно из потока №2 в поток №1 под будущие данные из GID.txt.

Задача была очень сложной и интересной, я перебрал что-то около  100 вариантов прежде чем смог сделать. И....

Оффтоп. В современных компах много процессоров на одном ядре. У каждого процессора есть своя кэш-память https://ru.wikipedia.org/wiki/%D0%9A%D1%8D%D1%88_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D0%B0

Если процессор поменял значение ячейки памяти, это значение остется только в кэше этого процессора. Но другой процессор может тоже захотеть "ознакомиться" с этой ячейкой. И вот чтобы другой процессор не увидел "старое значение" ячейки, существует специальный протокол MESI - https://habr.com/ru/articles/183834/

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

"Переменные" в Java - это отсылки на ячейки оперативной памяти, которые, при работе, тоже будут сидеть в кэш-памяти. То есть, я рассчитываю, что записав некоторое значение в память с потока №1, через несколько пикосекунд я смогу ознакомиться со значением в другом потоке.  

Конец оффтопа.

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

И врезался в ошибку... Алгоритм иногда(!) работал, иногда(!) нет. Ошибка была только на поздних релизах. Начал разбираться...

И в шоке выяснил, что в Java есть "оптимизатор": если "оптимизатор", условно, 1000 раз прочел ячейку и там наблюдал одно и то же значение, он делал "предположение", что в этой ячейке ВСЕГДА будет храниться одно и то же значение. И перекомпилировал код так, чтобы в программу всегда передавалось одно и то же "считанное" значение, без обращения к памяти.

То есть, я запускаю два потока.
1. Если "генератор" запускается раньше, чем "потребитель", то оптимизатор "потребителя" видит, что значения в ячейке постояно меняются "генератором": "генератор" запустился раньше и начал "срать" данными. Оптимизатор ничего не оптимизирует, продолжает читать из памяти.
2. Если "потребитель" запустился раньше "генератора", то "потребитель", условно, 1000 раз "крутанется", увидит, что 1000 раз там "ничего нет", запустится "оптимизатор" и отныне и до конца работы проги я буду получать "ничего нет!". "Потребитель", после отработки "оптимизатора" уже ничего не будет читать из памяти, просто будет "крутиться" в пустом цикле и ничего не будет делать. Только занимать процессор и греть воздух.

Добавлено (10.06.2024, 16:12)
---------------------------------------------
Что же предлагает джава,чтобы не нарваться на "оптимизатор"? По факту - "для передачи данных между  потоками используйте переменные типа volatile!" 

Volatile-переменные - дико медленные. При их использовании процессор блокирует шину передачи данных командой LOCK для остальных процессоров, а сведения отправляются напрямую из процессора в оперативную память. Все остальные процессоры  в этот момент сосут чупа-чупс стоят, если только не используют сведения из своей кэш-памяти. Команда LOCK используется для того, чтобы безопасно эксклюзивно обновить некую ячейку памяти. Но у меня специально было спроектировано так, чтобы этого не требовалось!

Сообщение отредактировал
V9 - Пятница, 07.06.2024, 21:19
 
  • Страница 10 из 10
  • «
  • 1
  • 2
  • 8
  • 9
  • 10
Поиск: