Многооконное редактирование

Редактировать сразу несколько файлов можно либо пользуясь командной редактора :e filename, либо указав все необходимые файлы в командной строке при вызове редактора (например: vi file1 file2 file3). В последнем случае вы двигаетесь по списку файлов с помощью команд:

:n - переходим к следующему файлу в списке

:rew - возвращаемся к редактированию первого файла в списке

Именованные буферы сохраняют свое содержимое при переходе к редактированию другого файла.

Параллелизм и его использование

Параллелизм

Параллельная обработка данных, воплощая идею одновременного выполнения нескольких действий, имеет две разновидности: конвейерность и собственно параллельность. Оба вида параллельной обработки интуитивно понятны, по­этому сделаем лишь небольшие пояснения.

Параллельная обработка. Если некое устройство выполняет одну операцию за единицу времени, то тысячу операций оно выполнит за тысячу единиц. Если предположить, что имеется пять таких же независимых устройств, способных работать одновременно и независимо, то ту же тысячу операций система из пя­ти устройств может выполнить уже не за тысячу, а за двести единиц времени. Аналогично, система из N устройств ту же работу выполнит примерно за 1000/N единиц времени.

Конвейерная обработка. Что необходимо для сложения двух вещественных чи­сел, представленных в форме с плавающей запятой? Целое множество мелких операций, таких как сравнение порядков, выравнивание порядков, сложение мантисс, нормализация и т.п. Процессоры первых компьютеров выполняли все эти "микрооперации" для каждой пары аргументов последовательно одна за другой до тех пор, пока не доходили до окончательного результата, и лишь по­сле этого переходили к обработке следующей пары слагаемых.

Идея конвейерной обработки заключается в выделении отдельных этапов вы­полнения общей операции, причем каждый этап, выполнив свою работу, пере­дает результат следующему, одновременно принимая новую порцию входных данных. Получаем очевидный выигрыш в скорости обработки за счет совмеще­ния прежде разнесенных во времени операций. Предположим, что в операции можно выделить пять микроопераций, каждая из которых выполняется за одну единицу времени. Если есть одно неделимое последовательное устройство, то 100 пар аргументов оно обработает за 500 единиц. Если же каждую микроопе­рацию выделить в отдельный этап (или иначе говорят - ступень) конвейерного устройства, то на пятой единице времени на разной стадии обработки такого устройства будут находиться первые пять пар аргументов, первый результат будет получен через 5 единиц времени, каждый следующий - через одну еди­ницу после предыдущего, а весь набор из ста пар будет обработан за 5+99=104 единицы времени, то есть будет получено ускорение по сравнению с последо­вательным устройством почти в пять раз (по числу ступеней конвейера).

Приблизительно так же будет и в общем случае. Если конвейерное устройство содержит l ступеней, а каждая ступень срабатывает за одну единицу времени, то время обработки n независимых операций этим устройством составит l+n-1 единиц. Если это же устройство использовать в монопольном режиме (как по­следовательное), то время обработки будет равно lxn. В результате получим ус­корение почти в l раз за счет использования конвейерной обработки данных.

Казалось бы, конвейерную обработку можно с успехом заменить обычным па­раллелизмом, для чего продублировать основное устройство столько раз, сколько ступеней конвейера предполагается выделить. Однако стоимость и сложность получившейся системы будет несопоставима со стоимостью и слож­ностью конвейерного варианта, а производительность будет почти такой же.

Для того чтобы написать параллельную программу, необходимо выделить в ней группы операций, которые могут вычисляться одновременно и независимо раз­ными процессорами, функциональными устройствами или же разными ступе­нями конвейера.

Возможность этого определяется наличием или отсутствием в программе ис­тинных информационных зависимостей. Две операции программы (а в данном случае под операцией можно понимать как отдельное срабатывание некоторого оператора, так и более крупные куски кода программы) называются информа­ционно зависимыми, если результат выполнения одной операции используется в качестве аргумента в другой. Очевидно, что если операция B информационно зависит от операции A (то есть, использует какие-то результаты операции A в качестве своих аргументов), то операция B может быть выполнена только по завершении операции A. С другой стороны, если операции A и B не являются информационно зависимыми, то алгоритмом не накладывается никаких огра­ничений на порядок их выполнения, в частности, они могут быть выполнены одновременно. Таким образом, задача распараллеливания программы обычно сводится к нахождению в ней достаточного количества информационно незави­симых операций, распределению их между вычислительными устройствами, обеспечению синхронизации и необходимых коммуникаций.

Введенное понятие информационной зависимости является достаточно про­стым, но исследование всего набора информационных зависимостей, сущест­вующих в реальной программе, является весьма сложной задачей. Достаточно представить себе программу, состоящую из десятков тысяч операторов, и учесть, что каждый цикл может состоять из огромного количества итераций, чтобы примерно представить себе сложность возникающих проблем. Для того чтобы формализовать задачу и облегчить анализ, вводится понятие графов ин­формационных зависимостей.

Вершинами в таких графах обычно являются некоторые операции программы, а в случае, если между двумя операциями существует информационная зависи­мость, то соответствующие этим операциям вершины соединяются направлен­ной дугой, началом которой является вершина-поставщик информации, а кон­цом - вершина-потребитель информации. Для упрощения исследования графа зависимостей в нем выделяется остовной подграф, имеющий минимальное чис­ло дуг при выполнении следующего условия: если две вершины графа зависи­мостей связаны путем, то они же должны быть связаны путем и в выделенном подграфе, который называется минимальным графом зависимостей. С помо­щью минимальных графов зависимостей можно решать все те же задачи, кото­рые можно решать и с помощью обычных графов зависимостей, однако они намного проще и в большинстве случаев позволяют производить эффективный анализ структуры зависимостей программы.

Если вершинам графа соответствуют отдельные срабатывания операторов про­граммы, то такой граф называется информационной историей выполнения про­граммы. Информационная история содержит максимально подробную инфор­мацию о структуре информационных зависимостей анализируемой программы, поэтому именно она используется при анализе программ с целью распаралле­ливания. Однако сложность анализа такова, что если в простых случаях можно построить и проанализировать получающийся граф вручную, то для больших реальных программ необходимы инструментальные программные средства.

Наши рекомендации