Ваш внутренний цикл перепрыгивает по всему массиву X
со смесью шагов, которые зависят от итерации внешнего цикла. Если n
и d
не достаточно малы, * это может привести к плохому использованию кэша - в последовательном коде тоже, но распараллеливание усилит этот эффект. По крайней мере X
не написана функцией, которая улучшает внешний вид. Кроме того, по-видимому, не существует каких-либо зависимостей данных между итерациями внешнего цикла, что хорошо.
Каков оптимальный способ разделения проблемы?
Вероятно, наилучшим доступным способом было бы разделить итерации внешнего цикла между вашими потоками. Для потоков T
один должен выполнить итерации 0
... (N / T) - 1
, второй - сделать (N / T) ... (2 * N / T) - 1
, и т. Д. ..
Как я мог значительноуменьшить время выполнения моего скрипта?
Первое, что I должен сделать, это использовать простое умножение вместо pow
для вычисления квадратов. Неясно, добьетесь ли вы чего-либо от параллелизма.
- Я уже пытался использовать pthreads асинхронно с помощью global_index, который навязывается мьютексу и local_index. [...]
Если вам нужно задействовать мьютекс, семафор или подобный объект синхронизации, тогда задача, вероятно, безнадежна. К счастью (возможно) в этом нет никакой необходимости. Динамическое назначение итераций внешнего цикла для потоков является слишком сложной задачей для этой проблемы. Статическое назначение итераций для потоков, как я уже описывал, устранит необходимость в такой синхронизации, и поскольку стоимость внутреннего цикла выглядит не так, как она будет сильно различаться для разных итераций внешнего цикла, вероятно, не будет слишком большой неэффективности, представленной, чтоway.
Другая идея состоит в том, чтобы заранее определить и разделить массив (скажем, на четыре равные части) и назначить вычисление каждого сегмента для данной pthread. Я не знаю, является ли это общей эффективной процедурой.
Это похоже на то, что я описал. Это одна из стандартных моделей планирования, предоставляемых OMP, и одна из наиболее эффективных, доступных для решения многих задач, учитывая, что она сама по себе не требует мьютекса. Однако он несколько чувствителен к взаимосвязи между количеством потоков и количеством доступных исполнительных блоков. Например, если вы распараллеливаете пять ядер на четырехъядерном компьютере, то одному придется подождать, пока не завершится работа одного из остальных - наилучшее теоретическое ускорение 60%. Распараллеливание одного и того же вычисления только по четырем ядрам более эффективно использует вычислительные ресурсы, обеспечивая лучшее теоретическое ускорение примерно на 75%.
* Если n
и d
довольно малы , скажем, что-нибудь удаленно близкое к значениям в примере программы драйвера, тогда накладные расходы, возникающие при распараллеливании, имеют хороший шанс преодолеть любые выгоды от параллельного выполнения.