" title="Написать письмо">Написать письмо
Донаты на карту ВТБ:
2200 4002 2461 6363

Статистика

Пользователи : 1
Статьи : 2458
Просмотры материалов : 10305901
 
Параллелизм: ускорение (15.07.2026). Печать E-mail
2026 - Июль
15.07.2026 14:41
Save & Share
Изучение особенностей параллелизма - похоже на сны при температуре 40. Если обычная многопоточность позволяет создать поток и заставить его что-нибудь отдельное лёгкое сделать, то параллелизм - раскидать одну огромную задачу на все логические процессоры ЦП, загрузить ЦП на ~100% - и при этом всё равно умереть со скуки в ожидании окончания работы. При этом, требуется не просто сверхточная работа - но и ускорение идеально написанных исходников.


Если описать вкратце все предыдущие серии (ссылки в каждом более раннем материале подтягивают ещё более ранние части), в контексте скоростей:
- нестабильность скорости работы потока. Нестабильность скорости работы группы потоков;
- влияние родительского потока на дочерние. Влияние дочерних потоков на родительский. Влияние дочерних потоков друг на друга. Даже если в потоке нет нагрузки, и он давно остановлен. Вплоть до подвешивания ОС;
- влияние исходного кода родительского потока на дочерние;
- возможное влияние настроек ОС и BIOS на дочерние потоки.

Предыдущая попытка оптимизировать исходники закончилась на сюре: время на сильных процессорах стало больше, чем на слабых. Сюр убрался сюрным решением: понижение приоритета родительского потока до минимума - через понижение приоритета всего приложения - через системную функцию SetPriorityClass: IDLE_PRIORITY_CLASS. Это же привело к другому положительному результату: влияние родительского потока на дочерние стало минимальным - и, например, теперь можно и Sleep() с любым числом вызывать, и ProcessMessages() сколь угодно раз (но убирать их из родительской функции всё равно нельзя). При этом, пониженным приложением прекрасно создаются дочерние потоки с приоритетом tpTimeCritical - неправильным распределением которых можно намертво подвесить ОС (если браузер открыт - есть вероятность и его падения из-за нехватки процессорного времени). Всё это - дало возможность расширения аналитического функционала для дочерних потоков, без понижения приоритета-скорости их работы.

Программное отключение высокоточного таймера HPET и переход на программный TSC (с сохранением аппаратного HPET в материнской плате) - дало невнятный результат: возможно, есть прирост ~1%. Но если учесть хаотичность времён отдельных потоков и суммарного времени работы группы потоков - этот 1% может быть погрешностью, и риски отключения программного HPET выше предполагаемого получаемого результата (хотя его отключение повышает FPS в играх - см. "Как правильно отключить HPET в Windows: пошаговый гайд по оптимизации таймеров" на IXBT).


Удивительно сильное увеличение скорости на 5.4% получилось при передаче указателей, а не значений, в самую частовызываемую и ресурсоёмкую функцию расчёта погрешности вычислений при работе с long double (4Б вместо 10Б, минус операция копирования). Дополнительное удивление в том, что итоговая погрешность была изначально известна и составляла 0.00046362 (это преднамеренный триггер: что на результат никакие эксперименты не влияют). Но, при изменении способа перемещения данных, стала 0.00044790. Это - полная задница: либо при копировании long double именно иногда порождается дополнительная погрешность (и она сейчас была убрана, и это является ошибкой при поиске погрешностей), либо какая-то ещё неточность где-то появилась.


Далее пошёл полный сюр (собственно, на скрине выше и видно). Время выполнения одного и того же кода - начало резко расти в процессе разработки, пока не достигло минимального значения 300+с: +25% от самого быстрого полученного результата. Выяснилось, что количество элементов на форме напрямую влияет на скорость дочерних потоков. При этом, имеет значение именно наличие элементов: ни Visible, ни Enabled не меняли ситуацию. Удаляешь 2 кнопки и текстовое поле справа сверху - 240с, запускаешь предыдущий вариант EXE-шника с ними - 300с. Перезагрузка - не помогает. На следующий день - проблема так же внезапно исчезла, как и появилась. Проблема не завязана на ЦП или ОС: 2 EXE-шника показывали совершенно разные результаты на разных ПК - как будто линковщик среды программирования единично засунул баг именно в исполняемый файл.

Продолжая добавлять элементы в ПО, время 240с увеличилось до 251с - и думалось, что в этом виноваты элементы интерфейса. Но когда начал добавлять пачками метки на форму - скорость не менялась. Поэтому, вопрос с элементами интерфейса остаётся открытым - но острота проблемы спала.

Неизвестно, как это объяснить: 251с превратилась в 235с - после того, как исходный код из CPP-файла формы перекидал в отдельные CPP-файлы. Мало того, была написана функция оценки состояния потоков - именно в CPP-файле, отвечающем за потоки. Есть предположение, что чем меньше кода пишешь в CPP-файле формы - тем лучше, хоть это и не имеет логики: наоборот, добавились вызовы отдельных функций, тратящих процессорное время. Возможно, это связано с выделением памяти в разных местах стека или основной памяти. В интернете пишут, что для каждого потока нужно делать свою отдельную область памяти и не лезть за пределы функции потока без необходимости. Может, действительно: вынесение операций в CPP-файл именно потоков - ускорило их размещением в другом месте RAM (хоть и используется один и тот же родительский поток).

Увеличение объёма работы для логических процессоров в 16 раз (увеличение точности вычисления погрешностей) - не устранило проблему разной скорости работы потоков - частоты логических процессоров не сильно плавают относительно друг друга. Работа почти 1.5ч - все потоки стали уже по 100%, а 2 плетутся на 90% ещё: ОС приспичило не разгонять их как все остальные (или кастрировать их номинальные частоты - прямо в момент создания).


2 способа работы с параллелизмом. Раздать потокам одинаковые порции задач и ждать, когда завершится последний. Разбить задачу на большое число порций - и кормить каждому освободившемуся потоку новую порцию. Второй, безусловно, быстрее; однако с ним не сможешь понять всех тонкостей работы потоков, не сможешь ускорить исходники - и можно получить на выходе второго способа время большее, чем оптимизированного первого. Уменьшение работы с 340с до 235с - это не шутки.

ПО работает необычно. При одном запуске, приложение сразу порождает 4 программных потока (видно на вкладке "подробности" диспетчера задач). Но это - минимум, может породить и 5, и 6, и 7. Может возникнуть мысль, что именно поэтому от запуска к запуску время работы одного и того же кода в одних и тех же условиях отличаются. Но это не так: даже если 4 потока при текущем запуске приложения вышло - первый запуск обработки данных даст время 235с, но оно никогда не будет достигнуто повторными запусками (всегда будет выше). На листках записаны значения на промежуточных этапах оптимизации: 241-305с с 10 запусков, 252-297 с 10 запусков. Первый запуск обработки данных - всегда самый быстрый; и даже несмотря на корректное уничтожение первой группы потоков (даже если байты занимаемой оперативной памяти просматривать) - что-то тормозит следующую группу потоков. Возможно, чтобы параллелизм работал максимально быстро при частых вызовах, - его нужно оформлять как отдельное приложение, которое жрёт данные/параметры из файла/RAM - и обрабатывает их, с последующей выдачей результатов и собственным уничтожением.

В некоторых новых средах программирования есть очень удобная фича: библиотека параллельных шаблонов PPL + одна лишь функция при её использовании (как будто однопоточный код пишешь - PPL сама раскидывает всё по логическим процессорам).

Вкусняшка E5-2696 V2 опять уделала все прочие ЦП по скорости работы: 189с.


Важный скрин увеличенной точности расчёта погрешностей уравнений прямой: максимальная погрешность сосредоточена и в первом, и в последнем потоке - и при этом одинаковая. Это значит, что она находится между минимальными и максимальными X1-Y1-X2-Y2. А это значит - можно сократить работу в 11-23 раза, обработав только числовую нагрузку первого потока, уже с максимальной точностью. А это значит, время на расчёты 20-40 дней - уменьшается до единиц дней. А там, глядишь, и дискрет анализа 6мин на мировой карте можно будет уменьшить ещё больше.


Надо бы эту заготовку по параллелизму закончить - и как отдельную программу выложить...

(добавлено 16.07.2026) Похоже, оптимизировать больше нечего, - углубился в поиск максимальной погрешности уравнений прямой:
- значение 4.479 - оказалось истинным: при работе с 23 ядрами - неправильно рассчитывался диапазон для последнего потока, выходя за предел необходимого;
- независимо от дискрета циклов, наибольшая погрешность продолжала находиться в первом и последнем потоке.


Каждое уменьшение шага приводило к сужению диапазона поиска, каждое сужение диапазона давало возможность уменьшить шаг ещё больше. В конечном итоге, был получен результат с шагом не изначальный 1 градус, а аж 1с.


Нет смысла делать вычисления до 1мс: видно, что точность увеличилась в 360 раз, - а погрешность не шибко больше стала. Таким образом, можно округлить максимальную погрешность до 0.0005.

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

(добавлено 21.07.2026) Выравнивание данных под архитектуру процессора. Весь интернет пестрит, что прирост в скорости даёт. Потратил целый день - нет прироста ни на каких операциях с объектами, содержащими данными (сравнивалось время: усреднение 100 измерений по 4.2млрд итераций). Только оперативка мусором забивается - не просто провальный результат, а и отрицательный.

(добавлено 22.07.2026) Не успел. СБ не понравилось, что на ПК стоит винда вместо линукса. Я отсутствовал - они уничтожили результаты вычислений за несколько дней, выключив ПК. Теперь вообще не уверен, что работа будет продолжена.

То есть, эти вредители не просто циферки на экране уничтожили. Они уничтожили возможность сравнить double с long double и заявить разным отделам разработки, что есть проблема точности разрабатываемого ими софта. И если учесть, что в одной миллисекунде карты мира содержится ~30см, - работа с double вместо long double может порождать погрешность вычислений в несколько метров (если не десятков). А это - промах для объектов, требующих высокой точности (например, капсулу космонавта сбросить чётко в выбранную зону).

(добавлено 25.07.2026) Не, ну это полный писец.

(добавлено 26.07.2026) Надо как-то корректно завершить эту работу. Выкладываю сюда завершённые исходники по расчёту (но без завершённых самих расчётов): 1.28МБ. А также CPP- и H-файлы функций по работе с потоками. Их можно использовать как заготовку, если поток всего 1. Если потоков много - 2-х файлов будет недостаточно: надо делать где-то 8: Threads_Main, Threads_Classes, Threads_Global, Threads_Executes и т.д.

(добавлено 27.07.2026) Пересмотрев исходники в блокноте - понял, что сильно накосячил, увлёкшись потоками (плюс напрочь забыл про проекцию Меркатора):
- по оси Y чисел должно быть в 2 раза меньше - скорость вычислений возрастает в 16 раз;
- нулевые координаты в левом нижнем углу карты, а не по её центру, - есть вероятность уменьшения погрешности в 2 раза;
- вместо if (uiMode == N) (планировалось 4 режима работы): нужно использовать if (bMode) - увеличение скорости работы;
- размер исходников стал меньше, т.к. из архива удалил сейчас временные файлы.

Портативная Windows 10 PE показывает 92% загрузки ЦП, в то время как непортативная - 100%. Скорее всего, родительский поток вообще не грузит систему. И так и неясно, какое число является верным в непортативной: там на одной вкладке диспетчера задач 100%, на другой 92%.

Частота логических процессоров ЦП - важнее частоты RAM при выборе конфигурации ПК для программирования. Иначе бы не удалось получить чёткую разницу во временах работы на разных ЦП. А на самом быстром, E5-2696 V2, - стоит вообще DDR3 1866МГц.
Обновлено ( 27.07.2026 19:19 )
 
 

Последние новости


©2008-2026. All Rights Reserved. Разработчик - " title="Сергей Белов">Сергей Белов. Материалы сайта предоставляются по принципу "как есть". Автор не несет никакой ответственности и не гарантирует отсутствие неправильных сведений и ошибок. Вся ответственность за использование материалов лежит полностью на читателях. Размещение материалов данного сайта на иных сайтах запрещено без указания активной ссылки на данный сайт-первоисточник (ГК РФ: ст.1259 п.1 + ст.1274 п.1-3).

Много статей не имеет срока устаревания. Есть смысл смотреть и 2011, и даже 2008 год. Политика сайта: написать статью, а потом обновлять ее много лет.
Рекламодателям! Перестаньте спамить мне на почту с предложениями о размещении рекламы на этом сайте. Я никогда спамером/рекламщиком не был и не буду!
Top.Mail.Ru