В информатике параллельная машина с произвольным доступом ( параллельное ОЗУ или PRAM ) — это абстрактная машина с общей памятью . Как следует из названия, PRAM представляет собой аналогию параллельных вычислений машине с произвольным доступом (RAM) (не путать с оперативной памятью ). [1] Точно так же, как ОЗУ используется разработчиками последовательных алгоритмов для моделирования производительности алгоритмов (например, временной сложности), PRAM используется разработчиками параллельных алгоритмов для моделирования производительности параллельных алгоритмов (например, временной сложности, когда обычно также указывается предполагаемое количество процессоров). Подобно тому, как модель RAM игнорирует практические вопросы, такие как время доступа к кэш-памяти по сравнению с основной памятью, модель PRAM игнорирует такие проблемы, как синхронизация и связь , но обеспечивает любое (зависящее от размера задачи) количество процессоров. Например, стоимость алгоритма оценивается с использованием двух параметров O(время) и O(время × номер_процессора).
Конфликты чтения/записи, обычно называемые блокировкой при одновременном доступе к одной и той же области общей памяти, разрешаются с помощью одной из следующих стратегий:
Здесь E и C означают «эксклюзивный» и «параллельный» соответственно. Чтение не вызывает расхождений, в то время как параллельная запись далее определяется как:
При рассмотрении разработки алгоритмов для PRAM делается несколько упрощающих предположений. Они есть:
Подобные алгоритмы полезны для понимания использования параллелизма, разделения исходной проблемы на схожие подзадачи и их параллельного решения. Введение формальной модели P-RAM в диссертации Уилли 1979 года [4] имело целью количественную оценку анализа параллельных алгоритмов способом, аналогичным машине Тьюринга . Анализ был сосредоточен на модели программирования MIMD с использованием модели CREW, но показал, что многие варианты, включая реализацию модели CRCW и реализацию на машине SIMD, были возможны только с постоянными накладными расходами.
Алгоритмы PRAM не могут быть распараллелены с помощью комбинации ЦП и динамической оперативной памяти (DRAM), поскольку DRAM не обеспечивает одновременный доступ к одному банку (даже к разным адресам в банке); но они могут быть реализованы аппаратно или выполнять чтение/запись во внутренние блоки статической оперативной памяти (SRAM) программируемой вентильной матрицы (FPGA), это можно сделать с использованием алгоритма CRCW.
Однако проверка практической значимости алгоритмов PRAM (или RAM) зависит от того, обеспечивает ли их модель стоимости эффективную абстракцию какого-либо компьютера; структура этого компьютера может сильно отличаться от абстрактной модели. Знание слоев программного и аппаратного обеспечения, которые необходимо вставить, выходит за рамки этой статьи. Но такие статьи, как Vishkin (2011), демонстрируют, как абстракция, подобная PRAM, может поддерживаться парадигмой явной многопоточности (XMT), а такие статьи, как Caragea & Vishkin (2011), демонстрируют, что алгоритм PRAM для задачи максимального потока может обеспечить значительное ускорение по сравнению с самой быстрой последовательной программой для той же задачи. В статье Ганим, Вишкин и Баруа (2018) показано, что алгоритмы PRAM сами по себе могут достичь конкурентоспособной производительности даже без каких-либо дополнительных усилий по преобразованию их в многопоточные программы на XMT.
Это пример кода SystemVerilog , который находит максимальное значение в массиве всего за 2 такта. Он сравнивает все комбинации элементов массива на первом такте и объединяет результат на втором такте. Он использует память CRCW; m[i] <= 1
и maxNo <= data[i]
пишутся одновременно. Параллелизм не вызывает конфликтов, поскольку алгоритм гарантирует, что одно и то же значение записывается в одну и ту же память. Этот код можно запустить на оборудовании FPGA .
модуль FindMax #( параметр int len = 8 ) ( входной бит тактовой частоты , сбросN , входной бит [ 7 : 0 ] данных [ len ], выходной бит [ 7 : 0 ] maxNo ); typedef enum bit [ 1 : 0 ] { COMPARE , MERGE , DONE } State ; Государство государство ; бит м [ лен ]; интервал я , j ; Always_ff @( posege clock , negedge resetN ) begin if ( ! resetN ) begin for ( i = 0 ; i < len ; i ++ ) m [ i ] <= 0 ; состояние <= СРАВНИТЬ ; конец еще начало регистр ( состояние ) СРАВНЕНИЕ: начало для ( я = 0 ; я < длина ; я ++ ) начало для ( j = 0 ; j < длина ; j ++ ) начало если ( данные [ я ] < данные [ j ]) м [ я ] <= 1 ; конец конечного состояния <= MERGE ; end MERGE: начать for ( i = 0 ; i < len ; i ++ ) начать if ( m [ i ] == 0 ) maxNo <= data [ я ]; конечное состояние <= ГОТОВО ; конец конца корпуса конец конца модуля