Шрифт:
Барьер синхронизации здесь реализуется с помощью операций pvm_barrier и pvm_joingroup . Реализация операторной функции для объекта задачи приве д ена в л истин г е 13.5.
Таблица 13.2. Групповые PVM-операции
int pvm_joingroup (char *groupname); Вносит вызывающий процесс в группу groupname, а затем возвращает int-значение, которое представляет собой номер процесса в этой группе
int pvm_lvgroup (char *groupname); Удаляет вызывающий процесс из группы groupname
int pvm_gsive (char *groupname); Возвращает int-значение, которое представляет собой количество членов в группе groupname
int pvm_gettid (char *groupname, int inum); Возвращает int-значение, равное идентификационному номеру задачи, выполняемой процессом, который идентифицируется именем группы groupname и номером экземпляра inum
int pvm_getinst (char *groupname, int taskid); Возвращает int-значение, которое представляет собой номер экземпляра, связанный с именем группы groupname и процессом, выполняющим задачу с идентификационным номером taskid
int pvm_barrier (char *groupname, int count); Блокирует вызывающий процесс до тех пор, пока count членов в группе groupname не вызовут эту функцию
int pvm_bcast (char *groupname, int messageid); Передает всем членам группы groupname сообщение, хранимое в активном буфере отправки, связанном с номером messageid
int pvm_reduce (void *operation, void *buffer, int count, int datatype, int messageid, char *groupname, int root); Выполняет глобальную операцию operation во всех процессах группы groupname
Рис.13.5. UML-диаграмма видов деятельности, отображающая синхронизацию «классной доски» и источников знаний
// Листинг 13.5. Определение функции operator // в классе task
void task::operator(string X) {
int cc; pvm_mytid;
cc = pvm_spawn(const_cast<char *>(X.data),NULL,0,"",l, &Tid[N]);
N++;
}
Функция-оператор operator используется для порождения PVM-задач. Имя задачи содержится в элементе X. data . При обращении к функции pvm_spawn (см. листинг 13.5) создается одна задача, а ее идентификационный номер сохраняется в элементе Tid[N] . (Подробнее о функции pvm_spawn и вызове PVM-задач см. гла-вуб.) Класс task используется для создания функциональных объектов (объектов-функций). При выполнении алгоритма
for_each(Solve.begin,Solve.end,Task);
вызывается функция operator , которая выполняет объект Task. Эта операция заставляет активизироваться источники знаний, содержа щ иеся в контейнере Solve. Алгоритм for_each гарантирует активизацию всех источников знаний. Если используется м одель SIMD, то в алгоритме for_each нет никакой необходимости. Вместо него прямо в конструкторе «классной доски» мы используем вызов функции pvm_spawn. В листинге 13.6 как раз и показано, как при использовании модели SIMD можно запустить множество PVM-задач из конструктора «классной доски».
// Листинг 13.6. Запуск PVM-задач из конструктора
// класса task
void task::operator(string X) {
int cc; pvm_mytid;
cc = pvm_spawn(const_cast<char *>(X.data),NULL,0,"",l, &Tid[N]);N++;
}
Связь «классной доски» и источников знаний
Согласно коду, приведенному в листинге 13.6, порождается 20 источников знаний. Сначала все они выполняют одинаковый код. После их порождения «классная доска» должна отправить сообщения с указанием, какую роль они будут играть в процессе решения задачи. При использовании данной конфигурации источники знаний и «классная доска» являются частью PVM-среды. После создания источники знаний будут взаимодействовать с «классной доской» путем соединения с портом, на котором она размещается, или по ее адресу в сети intranet или Internet. Для этого источникам знаний понадобится объектная ссылка на «классную доску». Эти ссылки можно «зашить» в код источников знаний, или они могут прочитать их из файла конфигурации либо получить из службы имен. Имея ссылку, источник знаний взаимодействует с ORB-брокером (Object Request Broker — брокер объектных запросов), чтобы найти удаленный объект, содержащий реальные данные (знания) и активизировать его. Для нашего примера мы назначаем «классной доске» конкретный порт и запускаем CORBA-объект «классной доски» с помощью следующей ко м анды,
blackboard -ORBIIOPAddr inet:porthos:12458
По этой команде запускается наша программа «классной доски» с подключением к порту 12458 хоста porthos. Запуск CORBA-объекта зависит от используемой CORBA-реализации. В данном случае мы используем «открытую» CORBA-реализацию Mico [25] При выполнении программы blackboard реализуется экземпляр «классной доски», который в свою очередь порождает источники знаний. В созданных источниках знаний жестко закодирован номер порта, по которому они будут связываться с «классной доской». Фрагмент кода реализации источника знаний, который связывается с CORBA - ориентированным объектом «классной доски», представлен в листинге 13.7.
// Листинг 13.7. Код источника знаний, который связывается
// с CORBA-ориентированной «классной доской»
1 #include «pvm3.h»
2 using namespace std;
3 #include <iostream>
4 #include <fstream>
5 #include <string.h>
6 #include <strstream>
7 #include «black_board_impl.h» 8
9 int main(int argc, char *argv[])
10 {
11 CORBA::ORB_var Orb = CORBA::ORB_init(argc, argv,«mico-local-orb»);
12 CORBA::Object_yar Obj =Orb->bind(«IDL:black_board:1.0»,«inet:por thos:12 4 5 8»);