Существует несколько разных подходов к программированию параллельных вычислительных систем:
Существует также большое количество инструментальных средств, которые упрощают проектирование параллельных программ (CODE, TRAPPER и др.).
Данная глава открывает рассмотрение первого из указанных подходов к программированию параллельных вычислительных систем.
Заметим, что языки типа Ассемблер отражают в себе систему команд и все особенности структуры параллельной вычислительной системы: число процессоров, состав и распределение регистров и оперативной памяти, систему коммутации и т. д. Ассемблер потенциально позволяет в наибольшей степени приспособить параллельный алгоритм к особенностям структуры конкретной параллельной ЭВМ и обеспечить наивысшую производительность ЭВМ. Несмотря на это, Ассемблер не используется широко для прикладного программирования параллельных ЭВМ по следующим причинам:
Имеется три основных подхода к созданию параллельных языков высокого уровня (ЯВУ).
Первый подход заключается во введении в состав традиционных последовательных ЯВУ средств поддержки параллелизма на уровне языковых конструкций или библиотечных функций. Достоинством подхода является простота освоения ЯВУ, а недостатками – противоречие концепций базового языка и параллельных средств, что затрудняет их реализацию и делает менее эффективной.
Второй подход состоит в создании оригинальных языков параллельной обработки, ориентированных на конкретную архитектуру или тип параллельных вычислительных систем (OCCAM, например). Достоинства подхода – возможность использования эффективно реализуемых, гибких языковых конструкций. Недостатки подхода – трудность освоения, низкая мобильность.
Третий - создание новых параллельных ЯВУ, не зависящих от конкретной архитектуры или типа параллельных вычислительных систем (АДА, например). Достоинство подхода состоит в возможности использования в ЯВУ концепций, повышающих эффективность и надежность написанных на этом языке программ; недостатки подхода – в трудности освоения и сложности создания эффективных объектных кодов при трансляции.

Примеры в данном и ряде последующих параграфов приводятся с использованием ЯВУ Actus, который представляет собой расширение языка Pascal - см. R. H. Perrott, "A language for array and vector processors," ACM Transactions on Programming Languages and Systems, Vol. 1, October 1979, pp. 177-195.
Векторно-конвейерные вычислительные системы и векторно-параллельные вычислительные системы ориентированы и имеют высокую эффективность при выполнении векторных операций. Векторы представляются в ЯВУ в виде массивов данных. Рассмотрим поэтому конструкции параллельных ЯВУ, используемые для работы с массивами.
Напомним понятия ранг массива и размерность массива. Рангом массива называется количество его измерений. Т.е. слова «-мерный массив» и «массив имеет ранг » являются синонимами. Размерностью массива называется количество элементов данных по каждому из измерений. Например, массив является трехмерным массивом (ранг равен трем) с размерностями ,,.
В параллельных ЯВУ можно выделить три подхода к представлению массивов:
1. Массивы - как последовательные объекты. В этом случае массивы описываются так же, как в последовательных ЯВУ. Параллелизм указывается только при обработке массивов (путем спецификации набора индексов элементов массивов, над которыми должна быть выполнена операция).
2. Массивы - как параллельные объекты. Здесь все массивы описываются как особые объекты заданной размерности. Любое обращение к массиву при этом подразумевает весь массив (хотя, естественно, не отменяется использование массива в качестве набора объектов меньшего ранга).
3. Массивы - как параллельные объекты Массивы - как смесь последовательных и параллельных объектов. В этом случае ограничивается количество размерностей, по которым массив может рассматриваться как параллельный объект. Любые следующие размерности должны быть индексированы. Данный подход неявно учитывает архитектуру используемой параллельной вычислительной системы.
Пример 1
В языке Actus массивы могут содержать массивы всех указанных типов:
var
(*одномерный параллельный массив*)
parvar: array [1:100] of integer;
(*одномерный последовательный массив*)
scalvar: array [1..50] of integer;
(*двумерный массив параллельных строк*)
grid: array [1:50, 1..100] of real;
Выборка объектов пониженного ранга.
Пусть имеется 2-х мерный -массив . Тогда выборка объектов пониженного ранга может выполняться с помощью следующих языковых конструкций:
Выборка диапазона значений.
Для выборки диапазона значений (сужение диапазона значений) по каждой из размерностей специфицируют начальное значение индекса, его приращение и конечное значение. Например,
- выборка внутренних точек массива;
- выборка первых трех элементов из всех нечетных строк.
Выборка с помощью целочисленных массивов.
Пусть , одномерные массивы из элементов, причем , , .
Рассмотрим 2-х мерный (4*4) -массив

и положим, что

, т.е. .
Возможны два существенно разных способа выборки с помощью целочисленных массивов, имеющих одинаковый синтаксис: проекционная выборка и линейное отображение.
Проекционная выборка с помощью целочисленных массивов. В этом случае результирующий объект имеет ранг меньший, чем ранг исходного объекта.
Если результирующий объект имеет вид , то ранг его равен единице и элементы определяются по правилу:
Таким образом, .
Если результирующий объект имеет вид , ранг его также равен единице и элементы определяются по правилу:
Таким образом, .
Линейное отображение с помощью целочисленных массивов. В этом случае результирующий объект имеет тот же ранг, что и ранг исходного объекта.
Если результирующий объект имеет вид , то ранг его равен двум и элементы определяются по правилу:
Таким образом,
Если результирующий объект имеет вид , то ранг его также равен двум и элементы определяются по правилу:
Таким образом, .
Если результирующий объект имеет вид , то ранг его также равен двум и элементы определяются по правилу:
Таким образом, .
Пример 2
В ЯВУ Actus используется линейное отображение с помощью параллельных целочисленных массивов. Пусть имеют место спецификации
const
(*параллельная константа*)
diagonal = 1:100 of integer;
var
(*параллельный массив*)
diag: array [1:100] of integer;
(*массив параллельных строк*)
para: array [1:100, 1..100] of real;
и присваивание (параллельное) diag [1:100] := diagonal. Тогда конструкция para[1:100,diag] означает все диагональные элементы массива para, доступ к которым может выполняться параллельно.
Выборка с помощью булевых массивов.
Пусть одномерный булевый массив из элементов. Так же, как в предыдущем разделе рассмотрим 2-х мерный (4*4) -массив =.
И в данном случае возможны два существенно разных способа выборки с помощью булевых массивов, имеющих одинаковый синтаксис: проекционная выборка и линейное отображение.
Проекционная выборка с помощью булевых массивов. В этом случае результирующий объект имеет ранг меньший, чем ранг исходного объекта. Массив , с помощью которого осуществляется выборка, должен иметь только один отличный от нуля элемент. Положим, что .
Если результирующий объект имеет вид , то ранг его равен единице и элементы определяются по правилу:
Таким образом, .
Если результирующий объект имеет вид , то ранг его также равен единице и элементы определяются по правилу
Таким образом, .
Линейное отображение с помощью булевых массивов. В этом случае результирующий объект имеет тот же ранг, что и ранг исходного объекта. Массив , с помощью которого осуществляется выборка, может иметь более одного отличного от нуля элемента. Положим, что .
Если результирующий объект имеет вид , то ранг его равен двум и элементы определяются по правилу:
Таким образом, .
Если результирующий объект имеет вид , то ранг его также равен двум и элементы определяются по правилу:
Таким образом, .
Выборка с помощью индексных множеств.
При данном способе выборки используются индексные множества. Поясним метод выборки с помощью индексных множеств примером.
Пример 3
Рассмотрим следующие спецификации и присваивания на языке Actus:
var
(*массив параллельных строк*)
para: array [1:100,1..100] of real;
index
(*множество целых чисел от 1 до 100, исключая числа 11 - 90*)
i=1:10,91:100;
(*множество нечетных чисел от 1 до 100*)
odd=1:(2)99;
(*множество четных чисел от 1 до 100*)
even=2:(2)100;
Тогда конструкция para [i,1..100] означает строки массива para, из которого исключены строки 11 – 90. Доступ к оставшимся строкам может выполняться параллельно. Аналогично, конструкция para [odd,1..100] означает нечетные строки массива para, а para [even,1..100] - четные строки массива para. Доступ к указанным строкам может выполняться параллельно.
Над индексными множествами в языке Actus определены теоретико-множественные операции объединения, пересечения и разности.
Индексация сдвигом.
Суть индексации сдвигом покажем на примере.
Пример 4
Рассмотрим фрагмент Actus-программы
var
(*параллельные одномерные массивы*)
para, parb: array [1:100] of integer;
index
(*множество целых чисел от 1 до 50*)
first50=1:50;
Тогда конструкция para [first50] := parb [first50] + parb [first50 shift 1] определяет параллельное сложение элементов 1 – 50 массива parb с элементами 2 – 51 этого же массива. Если значение целого выражения после операторов shift, rotate положительно, то сдвиг осуществляется «справа налево». В противном случае – «слева направо».