Создание MPI - интерфейса для сетевого кластера

Страницы работы

Содержание работы

Лабораторная работа  №7

Создание MPI - интерфейса для сетевого кластера.

Цель работы: Изучение и разработка интерфейса передачи сообщений для параллельных приложений. Необходимо создать библиотеку функций MPI - интерфейса  для кластера на базе сети Novell Netware.

Выполнение работы:

          В данной работе используются функции из лабораторной работы №6, повторно их текст не приводится.

Структура данных для коммуникатора, используемого для связи между ветвями приложения.

typedef struct

{

// управляющие блоки для различных операций

            NCB reset_ncb;

            NCB adapter_status_ncb;

            NCB session_status_ncb;

            NCB call_ncb;

            NCB listen_ncb;

            NCB add_name_ncb;

            NCB add_group_name_ncb;

            NCB delete_name_ncb;

            NCB send_ncb;

            NCB receive_ncb;

            NCB receive_any_ncb;

            NCB hangup_ncb;

            NCB temp_ncb;

            NCB send_datagram_ncb;

            NCB receive_datagram_ncb;

            NCB send_bcst_datagram_ncb;

            NCB receive_bcst_datagram_ncb;

            NCB cancel_ncb;

            byte pos; // Номер ветви, определяется в процессе инициализации

            byte cur; // Номер ветви, с которой устанавливается соединение

            byte num; // Номер имени ветви (NetBios)

            char name[16]; // Имя ветви (NetBios)

            byte progress; // Указание того, что идут вычисления

            byte ack; // Количество ответивших серверу ветвей (сбор результатов)

            double summary; // результат

            long time_sec; // Время начала вычислений, в секундах

            short time_mili; // Время начала вычислений, тысячные секунды

} COMM;

COMM MPI_COMM_WORLD – коммуникатор, создаваемый при инициализации ветви

Функции MPI

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

int MPI_Comm_size(COMM comm, int *size)

{

            STATUS_INFO info;

            name_status(comm, comm.name, &info);

            int duplicate = 0, i, j;

            char name[16], *off;

            name_status(MPI_COMM_WORLD, MPI_COMM_WORLD.name, &info);

            for (i = 0,j = 0; i < info.session_count; i++) {

                        if (info.session_data[i].state != 3)

                                    continue;

                        strcpy(name, info.session_data[i].remote_name);

                        off = name + 6;

                        if (atoi(off) == MPI_COMM_WORLD.pos && duplicate) {

                                    continue;

                        }

                        j++;

                        if (atoi(off) == MPI_COMM_WORLD.pos) {

                                    duplicate = 1;

                        }

            }

            *size = j - 1;

            return 0;

}

Функция возвращает номер ветви, данные получаются из коммуникатора

int MPI_Comm_rank(COMM comm, int *rank)

{

            *rank = comm.pos - 1;

            return 0;

}

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

int MPI_Recv(void *buf, int count, int source, COMM &comm)

{

            if (source == MPI_ANY_SOURCE)

                        return receive_any(comm, post_handle, buf, count);

            else

                        return -1;

}

Функция передачи сообщения в заданную ветвь

int MPI_Send(void *buf, int count, int dest, COMM &comm)

{

            STATUS_INFO info;

            byte lsn;

            char name[16], temp[16], dest_char[16];

            strcpy(temp, "Worker");

            itoa(dest, dest_char, 10);

            strcat(temp, dest_char);

            real_name(name, temp);

            name_status(MPI_COMM_WORLD, MPI_COMM_WORLD.name, &info);

            for (int i = 0; i < info.session_count; i++) {

                        if (!strcmp(name,info.session_data[i].remote_name)) {

                                    lsn = info.session_data[i].lsn;

                                    break;

                        }

            }

            return send(comm, lsn, buf, count);

}

Функция инициализации MPI. Ветвь последовательно перебирает номера, отыскивая первой свободное, регистрируется с этим именем, устанавливает соединения с собой и переходит в режим listen any, для того, чтобы последующие ветви могли установить с ней соединение. Константа MAX_WORKER определяет максимально возможное количество ветвей и задается на этапе компиляции.

int MPI_Init(int argc,char* argv[])

{

            puts("Выполняется функция MPI_Init");

            check_netbios();

            char name[16], temp[4];

            int i;

            MPI_COMM_WORLD.progress = 0;

            MPI_COMM_WORLD.ack = 0;

            for(i = 1; i <= MAX_WORKER; i++) {

                        strcpy(name, "Worker");

                        itoa(i, temp, 10);

                        strcat(name, temp);

                        if (add_name(MPI_COMM_WORLD, name)) {

                                    continue;

                        }

                        else {

                                    printf("Удалось зарегистрироваться под именем %s\n", name);

                                    strcpy(MPI_COMM_WORLD.name, name);

                                    MPI_COMM_WORLD.pos = i;

                                    MPI_COMM_WORLD.cur = 1;                      

MPI_COMM_WORLD.num =

MPI_COMM_WORLD.add_name_ncb.NCB_NUM;

                                    listen(MPI_COMM_WORLD, "*", name, post_handle, 20, 20);

                                    call(MPI_COMM_WORLD, "Worker1", name, post_handle, 20, 20);

                                    break;

                        }

            }

            if (i > MAX_WORKER) {

                        printf("Лимит участников превышен, завершение MPI_Init.\n");

                        puts("Нажмите любую клавишу для выхода");

                        bioskey(0);

                        exit(1);

            }

            return 0;

}

Функция завершения работы ветви. Функция kill() разрывает все активные соединения.

int MPI_Finalize()

{

            puts("Выполняется функция MPI_Finalize");

            cancel(MPI_COMM_WORLD, post_handle, &MPI_COMM_WORLD.receive_any_ncb);

            cancel(MPI_COMM_WORLD, post_handle, &MPI_COMM_WORLD.listen_ncb);

            kill(MPI_COMM_WORLD);

            printf("Удаляю имя %s из таблицы имен\n", strip_name(MPI_COMM_WORLD.name));

            delete_name(MPI_COMM_WORLD, MPI_COMM_WORLD.name);

            return 0;

}

Тестирование (путем непосредственного использования) данных функций производится в лабораторной работе №8.

Похожие материалы

Информация о работе