next up previous contents
Next: Ассоциирование информации со статусом Up: Обобщенные запросы Previous: Обобщенные запросы   Contents

Примеры

Пример 6.1. Этот пример показывает код для определяемой пользователем небольшой операции над типом int с использованием бинарного дерева: каждый некорневой узел получает два сообщения, суммирует их содержимое, и посылает на уровень выше. Принимается, что никакого статуса не возвращается и что операция не может быть отменена.

typedef struct { MPI_Comm comm; int tag; int root; int valin; int *valout; MPI_Request request; } ARGS;

int myreduce(MPI_Comm comm, int tag, int root, int valin, int *valout, MPI_Request *request) { ARGS *args; pthread_t thread; /* Запрос стартует */ MPI_Grequest_start(query_fn, free_fn, cancel_fn, NULL, request); args = (ARGS*)malloc(sizeof(ARGS)); args->comm = comm; args->tag = tag; args->root = root; args->valin = valin; args->valout = valout; args->request = *request; /* Нить узла обработки запроса */ /* Доступность вызова pthread_create определяется системой */ pthread_create(&thread, NULL, reduce_thread, args); return MPI_SUCCESS; }

/* код нити*/ void reduce_thread(void *ptr) { int Ichild, rchild, parent, lval, rval, val; MPI_Request req[2]; ARGS *args; args = (ARGS*)ptr; /* Определение ссылкок вниз влево, вниз вправо и вверх для узла дерева; */ /* Установка в MPI_PROC_NULL если ссылки не существуют */ /* Код не показан */ ... MPI_Irecv(&lval, 1, MPI_INT, lchild, args->tag, args->comm, &req[0]); MPI_Irecv(&rval, 1, MPI_INT, rchild, args->tag, args->comm, &req[l]); MPI_Waitall(2, req, \verb|MPI_STATUSES_IGNORE|) ; val = Ival + args->valin + rval; MPI_Send( &val, 1, MPI_INT, parent, args->tag, args->comm ); if (parent == MPI_PROC_NULL) *(args->valout) = val; MPI_Grequest_complete ((args->request)); free(ptr) ; return ; }

int \verb|query_fn|(void *extra_state, MPI_Status *status) { /* Всегда посылает только int */ MPI_Status_set_elements (status, MPI_INT, 1); /* Никогда нельзя отменить т.к. всегда истинна */ MPI_Status_set_cancelled(status, 0); /* Выбрано, что для этого ничего не возвращается */ status->MPI_SOURCE = MPI_UNDEFINED; /* Тэг не имеет смысла для этого обобщенного запроса */ status->MPI_TAG = MPI_UNDEFINED; /* Этот обобщенный запрос всегда выполняется */ return MPI_SUCCESS; }

int \verb|free_fn|(void *extra_state) { /* Этот обобщенный запрос не требует никакого освобождения т.к. всегда выполняется */ return MPI_SUCCESS; }

int cancel_fn(void *extra_state, int complete) { /* Этот обобщенный запрос не поддерживает отмену. */ /*Выход Ц, если уже выполнен. */ /*Если выполнен, то нить такая же, как и для случая с отменой. */ if (!complete) { fprintf (stderr, "Cannot cancel generalized request - aborting program\n"); MPI_Abort(MPI_COMM_WORLD, 99); } return MPI_SUCCESS; }



Alex Otwagin 2002-12-10