Как Java управляет многопоточным доступом к элементам массивов?

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

Я подозреваю, что эта медленная параллельная обработка происходит из-за переключения контекста . А может это из-за «автоматической» синхронизации общих объектов. Я думаю, вы можете помочь мне понять, что происходит.

Позвольте мне изложить мой случай: я делаю программу для научных расчетов. Он не зависит от внешних факторов, только от входных значений, которые я ему даю в начале. Размер этой проблемы можно измерить нс (это имя, которое я использую). Его можно рассматривать как «разрешение» решения, это один из вводимых пользователем данных, обычно порядка 100.

Таким образом, у меня есть несколько массивов double в моем основном классе, например double ys [Ns] [N] или phiS [Ns] [Nord] [N] , где N и Nord - другие фиксированные величины программы. В моей программе я должен вычислить несколько вещей для каждой из точек Ns , и вот идет распараллеливание. Расчет каждой точки независим, поэтому я могу разделить их на разные потоки и надеяться, что это будет быстрее.

Итак, вместо цикла for (int i = 0; i Я разделил эту вычислительную обязанность на Runnable-пакеты, каждый из которых находится в меньшем интервале: for (int i = start; i , где start и end всегда находятся в диапазоне от 0 до Ns. Например, если я использую двухъядерный компьютер, я делаю две партии: одна с start = 0 и end = Ns / 2 , другая с start = Ns / 2 и end = Ns . Если я на четырехъядерном, вторая партия будет иметь от start = Ns / 4 до end = Ns / 2 и так далее (при условии точного разделения в каждом случае).

Каждая партия, как a Класс, реализующий Runnable, хранится в ArrayList и передается в FixedThreadPool с размером, равным количеству ядер. Он выполняет пакеты и ожидает их завершения, используя простую схему CountDown .

Каждому из этих пакетов требуется доступ к данным в этих массивах из основного класса программы, но их доступ таков, что каждый пакет читает только с yS [start] [] до yS [end] [] и поэтому два пакета никогда не будут пытаться прочитать один и тот же элемент массива. Интересно, по-прежнему ли Java блокирует yS, даже если каждая партия не работает? t пытается получить доступ к тем же элементам, что и другие.

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

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

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

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

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

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

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

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

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

Итак, подведем итог, вопрос: почему я не получаю выгоду от многопоточности, когда я ожидал?

Я только что запускал здесь пару раз простой последовательный и многопоточную программу и получил 14500 мс для последовательного порта и 15651 мс для многопоточности. Оба на одном Dual Core. Еще одно замечание: при последовательном запуске каждое вычисление (от 0 до нс) занимает от 1,1 до 4,5 мс. В двухпотоковом режиме каждый пакет (Ns / 2 точки) занимает от 0,5 до 3 мс; (измеряется сверху вниз в методе run (). Каждый раз при вычислении отличается своей числовой сходимостью)

Большое спасибо за внимание.

5
задан Community 23 May 2017 в 11:52
поделиться