Многооконное редактирование
Редактировать сразу несколько файлов можно либо пользуясь командной редактора :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 не являются информационно зависимыми, то алгоритмом не накладывается никаких ограничений на порядок их выполнения, в частности, они могут быть выполнены одновременно. Таким образом, задача распараллеливания программы обычно сводится к нахождению в ней достаточного количества информационно независимых операций, распределению их между вычислительными устройствами, обеспечению синхронизации и необходимых коммуникаций.
Введенное понятие информационной зависимости является достаточно простым, но исследование всего набора информационных зависимостей, существующих в реальной программе, является весьма сложной задачей. Достаточно представить себе программу, состоящую из десятков тысяч операторов, и учесть, что каждый цикл может состоять из огромного количества итераций, чтобы примерно представить себе сложность возникающих проблем. Для того чтобы формализовать задачу и облегчить анализ, вводится понятие графов информационных зависимостей.
Вершинами в таких графах обычно являются некоторые операции программы, а в случае, если между двумя операциями существует информационная зависимость, то соответствующие этим операциям вершины соединяются направленной дугой, началом которой является вершина-поставщик информации, а концом - вершина-потребитель информации. Для упрощения исследования графа зависимостей в нем выделяется остовной подграф, имеющий минимальное число дуг при выполнении следующего условия: если две вершины графа зависимостей связаны путем, то они же должны быть связаны путем и в выделенном подграфе, который называется минимальным графом зависимостей. С помощью минимальных графов зависимостей можно решать все те же задачи, которые можно решать и с помощью обычных графов зависимостей, однако они намного проще и в большинстве случаев позволяют производить эффективный анализ структуры зависимостей программы.
Если вершинам графа соответствуют отдельные срабатывания операторов программы, то такой граф называется информационной историей выполнения программы. Информационная история содержит максимально подробную информацию о структуре информационных зависимостей анализируемой программы, поэтому именно она используется при анализе программ с целью распараллеливания. Однако сложность анализа такова, что если в простых случаях можно построить и проанализировать получающийся граф вручную, то для больших реальных программ необходимы инструментальные программные средства.