Inferno OS Wiki
Регистрация
Advertisement

Автор: Caerwyn Jones

Источник: gmane.os.inferno.general


Это пособие посвящено настройке простой вычислительной сети (Grid) при помощи inferno. Эти инструкции должны работать, несмотря на то, что могут быть не вполне реалистичными, однако надесь, они представят вам кусочки из которых вы сможете посторить свою собственную вычислительную сеть.

Я буду проводить настройку множества узлов, но я буду делать это все на одной машине. Этот пример остается полезным в случае многоядерного компьютера. Я предполагаю, что все рассмотренные ниже примеры запускаются в acme-sac.

Ведущим звеном вычислительной сети inferno является registry(4). Мы должны запустить в нашей вычислительной сети только одну службу registry. Во-первых, отредактируйте /lib/ndb/local и установите значение registry для infernosite.

	infernosite=
		registry=localhost

Я напишу маленькую библиотеку функций для командного интерпретатора shell для многократного запуска частей grid. Запустите acme-sac и создайте новый файл под названием gridlib. Добавьте туда команды, описанные ниже. Мы хотим назначить один узел (сессию acme-sac) мастером, а всех остальных рабочими.

Следующая функция запускает registry и экспортирует файловую систему registry.

fn masterinit {
	ndb/cs
	mount -A -c {ndb/registry} /mnt/registry
	listen -A -v 'tcp!*!registry' {export /mnt/registry&}
}

Каждый рабочий должен примонтировать файловую систему registry.

fn workerinit {
	ndb/cs
	mount -A 'net!$registry!registry' /mnt/registry
}

Откройте новый экземпляр acme-sac чтобы запустить его как мастер-сервер. Откройте новое окно при помощи 'win' и запустите masterinit.

	% run gridlib
	% masterinit

Каждый рабочий экспортирует rstyx чтобы иметь возможность запускать команды. Мы хотим, чтобы все, что мы запускаем, использовало grid для регистрации в registry.

Команда 'newcpu' зарегистрирует новый сервис rstyx.

fn newcpu {
	grid/reglisten -A -r svc rstyx 'tcp!*!0' {auxi/rstyxd&}
}

Запустите еще несколько редакторов acme-sac и запустите в каждом функцию workerinit из gridlib.

	% run gridlib
	% workerinit
	% newcpu

Если вы посмотрите командой 'ls' содержимое /mnt/registry из любого узла, вы должны увидеть все сервисы всех рабочих. Откройте /mnt/registry/index для получения подробностей. Вы можете добавить больше атрибутов к вашему сервису путем их передачи в качестве аргументов reglisten.

Теперь давайте запустим одновременно одну и ту же команду на всех cpu. Эта команда использует ndb/regquery для поиска всех сервисов rstyx, затем на каждом будет выполнена rcmd для запуска удаленной команды. Мы сделаем это в фоновом режиме и соберем идентификаторы процессов (pid) каждой rcmd, которые мы затем используем в конце для ожидания завершения всех работ.

fn rsplit {
	args := $*
	rpid := ()
	for i in `{ndb/regquery -n svc rstyx} {
		rcmd -A $i $args &
		rpid = $apid $rpid
	}
	for i in  /prog/ ^ $rpid ^/wait {read < $i  } >/dev/null >[2=1]
}

Ниже приведен пример запуска.

% rsplit math/linbench 200
   28.79 Mflops      0.2 secs
   24.72 Mflops      0.2 secs
   43.31 Mflops      0.1 secs

Если у вас многоядерная машина вы можете попробовать запустить разное число узлов для полной утилизации CPU.

Простой пример Grid. Часть 2

Я хочу показать вам еще несколько ключевых моментов, касающихся inferno, которые будут полезны при построении среды распределенных вычислений. Я покажу вам действительно простой пример подачи данных всем процессам-рабочим.

Настройте grid как это было описано в предыдущей части.

Это будет примером многоядерной утилиты grep(1), которой я буду посылать имена файлов для множества grep-рабочих. Существует много разных способов достичь этого. Суть в том, чтобы показать больше возможностей Inferno, которые выделяют ее характерные свойства.

Одно из таких свойств состоит в том, что rcmd экспортирует локальное пространство имен удаленной команде; мы можем использовать это для передачи информации чтобы управлять удаленным процессом. Пространство имен монтируется в /n/client. Посмотрите на этот пример,

	% rcmd -A ${nextcpu} ls /n/client

Запомните, что это намного больше чем просто дисковая файловая система. Мы можем создать именованые пайпы/каналы (pipes) и передавать данные от одного локального ко множеству удаленных процессов через pipe(3).

Создадим именованный пайп

	
	% mkdir /tmp/rpipe
	% bind '#|' /tmp/rpipe

Простой пример использования пайпа (сначала запустим читающий процесс),

	% rcmd -A ${nextcpu} cat /n/client/tmp/rpipe/data1 &
	% du -a > /tmp/rpipe/data

Я определял функцию rsplit в предыдущей части, однако она работает только для команд .dis, так что я должен подкорректировать ее для работы с блоками команд командного интерпретатора, заключенными в фигурные скобки (другое важное качество inferno).

fn rsplit {
	args := $*
	rpid := ()
	for i in `{ndb/regquery -n svc rstyx} {
		rcmd -A $i sh -c ${quote $"args }&
		rpid = $apid $rpid
	}
	for i in  /prog/ ^ $rpid ^/wait {read < $i  } >/dev/null >[2=1]
}

Я собираюсь использовать команду fs(1) для обхода дерева файлов и печати путей. Например, я хочу распечатать все файлы с исходных кодом limbo.

fn limbofiles {
	fs print  {select {mode -d}  {filter -d {match -ar '.*\.(b|m)$'} {walk /appl}} }
}

Теперь я связываю pipe, fs, и rsplit вместе и получаю распределенный grep.

fn lk {
	re = $1
	bind '#|' /tmp/rpipe
	rsplit {
		re=`{cat /n/client/env/re};
		getlines {grep -i $re $line /dev/null} < /n/client/tmp/rpipe/data1
	}&
	sid := $apid
	limbofiles > /tmp/rpipe/data
	read < /prog/ ^ $sid ^ /wait  >/dev/null >[2=1]
}

Несколько замечаний об этом коде. Я установил переменную окружения 're' как первый аргумент lk. Файловая система env(3) так же экспортируется как часть пространства имен команды rcmd, таким образом я могу читать значение 're' любого рабочего,

	re=`{cat /n/client/env/re}

Я использовал строенную в sh-std(1) команду 'getlines' для построчного чтения из пайпа и запуска grep (/dev/null для принуждения grep печатать имена файлов). Последняя строка ожидает завершения команды rsplit.

Вы можете запустить lk как показано ниже,

	% lk wmexport

Далее показаны необработанные примерные показатели запуска настоящей простой распределенной сети на компьютерах с 4-х ядерными Xeon 2.4GHz.

# одна виртуальная машина (ВМ)
% time sh -c 'limbofiles | getlines {grep wmexport $line /dev/null}'
0l 14.11r 14.11t

# четыре ВМ
% time sh -c 'lk wmexport'
 0l 7.172r 7.172t

# четыре ВМ
% time sh -c 'rsplit {math/linbench 1000}'
   55.08 Mflops     12.1 secs
   53.76 Mflops     12.4 secs
   53.76 Mflops     12.4 secs
   53.63 Mflops     12.5 secs
0l 13.06r 13.06t

# одна ВМ с параллельными задачами
%  time sh -c '{math/linbench 1000& math/linbench 1000 & math/linbench
1000 & math/linbench 1000}'
   39.01 Mflops     17.1 secs
   39.05 Mflops     17.1 secs
   40.11 Mflops     16.7 secs
   40.18 Mflops     16.6 secs
0l 18.2r 18.2t

# одна ВМ с последовательными задачами
% time sh -c '{math/linbench 1000; math/linbench 1000 ; math/linbench
1000 ; math/linbench 1000}'
  154.50 Mflops      4.3 secs
  155.07 Mflops      4.3 secs
  151.21 Mflops      4.4 secs
  154.50 Mflops      4.3 secs
0l 18.17r 18.17t

Caerwyn

Advertisement