Здравствуйте, коллеги-программисты.Я уже задавал один вопрос , но, несмотря на действительно хорошие ответы, которые я получил, я не смог решить мою проблему.Затем я потратил время на рефакторинг своего кода таким образом, чтобы улучшить его потенциал распараллеливания (имея меньше пакетов вычислений с большим количеством вычислительных обязанностей в каждой).Но все же я не могу иметь лучшую производительность, чем последовательная обработка.
Я подозреваю, что эта медленная параллельная обработка происходит из-за переключения контекста .Или может быть из-за «автоматической» синхронизации общих объектов.Я думаю, что вы можете помочь мне понять, что происходит.
Позвольте мне изложить мой случай: я делаю программу для научных расчетов.Это не зависит от внешних вещей, только от входных значений, которые я даю ему при его запуске.Размер этой проблемы можно измерить с помощью Ns
(это имя я использую).Это можно рассматривать как «разрешение» решения, оно является одним из пользовательских вводов и обычно имеет порядок 100.
Таким образом, в моем основном классе есть несколько двойных массивов, напримеркак двойной ys[Ns][N]
или phiS[Ns][Nord][N]
, где N и Nord - другие фиксированные величины программы.В моей программе я должен рассчитать несколько вещей для каждой из Ns
точек, и здесь идет распараллеливание.Каждое вычисление точек является независимым, поэтому я могу разделить их на разные потоки и надеяться, что оно станет быстрее.
Таким образом, вместо цикла for (int i=0; i<Ns; <i++)
я разделил эту вычислительную обязанность на Runnable партии, каждая из которых находится в пределахменьший интервал: for (int i=start; i<end; i++)
, где начало и конец всегда между 0 и Ns.Например, если я работаю на двухъядерном компьютере, я делаю две партии, одну с start = 0
и end = Ns/2
, другую с start = Ns/2
и end = Ns
.Если я работаю на четырехъядерном процессоре, вторая партия будет иметь start = Ns/4
до end = Ns/2
и т. Д. (При условии, что деление является точным в каждом случае).
Каждая партия, как класс, реализующий Runnable, сохраняется в ArrayList<Batch>
и присваивается FixedThreadPool
с размером, равным количеству ядер.Он выполняет партии и ожидает их завершения, используя простую схему CountDown
.
Каждый из этих пакетов должен иметь доступ к данным этих массивов из основного класса программы, но их доступ таков, что каждый пакет читает только от yS[start][]
до yS[end][]
, и поэтому две партии никогда не будутпопробуйте прочитать тот же элемент массива.Интересно, Java все еще блокирует yS, даже если каждый пакет не пытается получить доступ к тем же элементам, что и другие.
Интересно также, связана ли моя проблема с издержками из-за переключения контекста, поскольку каждый пакетНужно иметь дело с тысячами двойников, и если способ, которым построена программа, может повлиять на это.
Может быть, мне нужно найти способ передать каждой партии только те элементы массивов, которые имеют к ней отношение, но я не знаю, как к этому подойти.Если бы были указатели, я мог бы иметь новые массивы только нужных элементов с простыми операциями с указателями и без перераспределения чего-либо.Есть ли способ сделать такую вещь в Java?
Ну, наконец, просто упомянуть: есть одна часть кода, которую нужно синхронизировать (она имеет дело с другими массивами), и она уже работаетхорошо.Эти расчетные обязанности, которые я описал выше, не единственные, что делает моя программа.Они находятся внутри цикла, чередуясь с последовательными частями обработки, но они действительно важны как общее время выполнения.
Итак, подведем итог: вопрос в том, почему я не получаю многопоточность, когда я ожидалto?
Я просто пару раз запускал здесь простой последовательный порт и многопоточную программу и получил 14500 мс для последовательного и 15651 мс для многопоточного.Оба на одном Dual Core.Другой момент, на который следует обратить внимание: при серийном запуске каждая расчетная нагрузка (от 0 до Ns) занимает от 1,1 до 4,5 мс.При двойной резьбе на каждую партию (нс / 2 точки) уходит от 0,5 до 3 мс;(измеряется сверху вниз для метода run (). Каждый раз, когда расчетная пошлина отличается своей числовой сходимостью)
Большое спасибо за внимание.