LAPI_Amsend Subroutine

Propósito

Transfere uma mensagem de usuário para uma tarefa remota, obtendo o endereço de destino na tarefa remota a partir de um manipulador de cabeçalho especificado pelo usuário.

Biblioteca

Biblioteca de Disponibilidade (liblapi_r.a)

Sintaxe C

#include <lapi.h>
 
typedef void (compl_hndlr_t) (hndl, user_info);

lapi_handle_t *hndl;       /* pointer to LAPI context passed in from LAPI_Amsend */
void           *user_info;  /* buffer (user_info) pointer passed in               */ 
                            /* from header handler (void *(hdr_hndlr_t))          */

 
typedef void *(hdr_hndlr_t)(hndl, uhdr, uhdr_len, msg_len, comp_h, user_info);

lapi_handle_t   *hndl;       /* pointer to LAPI context passed in from LAPI_Amsend */
void            *uhdr;       /* uhdr passed in from LAPI_Amsend                    */
uint            *uhdr_len;   /* uhdr_len passed in from LAPI_Amsend                */
ulong           *msg_len;    /* udata_len passed in fom LAPI_Amsend                */
compl_hndlr_t  **comp_h;     /* function address of completion handler             */
                             /* (void (compl_hndlr_t)) that needs to be filled     */ 
                             /* out by this header handler function.               */
void           **user_info;  /* pointer to the parameter to be passed              */
                             /* in to the completion handler                       */
 

int LAPI_Amsend(hndl, tgt, hdr_hdl, uhdr, uhdr_len, udata, udata_len, 
                tgt_cntr, org_cntr, cmpl_cntr)
 
lapi_handle_t  hndl;
uint           tgt;
void          *hdr_hdl;
void          *uhdr;
uint           uhdr_len;
void          *udata;
ulong          udata_len;
lapi_cntr_t   *tgt_cntr;
lapi_cntr_t   *org_cntr;
lapi_cntr_t   *cmpl_cntr;

Sintaxe FORTRAN

include 'lapif.h'
 
INTEGER SUBROUTINE COMPL_H (hndl, user_info)
INTEGER hndl
INTEGER user_info
 
INTEGER FUNCTION HDR_HDL (hndl, uhdr, uhdr_len, msg_len, comp_h, user_info)
INTEGER hndl
INTEGER uhdr
INTEGER uhdr_len
INTEGER (KIND=LAPI_LONG_TYPE) :: msg_len	     
EXTERNAL INTEGER FUNCTION comp_h
TYPE (LAPI_ADDR_T) :: user_info
 
LAPI_AMSEND(hndl, tgt, hdr_hdl, uhdr, uhdr_len, udata, udata_len,  
            tgt_cntr, org_cntr, cmpl_cntr,  ierror)
INTEGER hndl
INTEGER tgt
EXTERNAL INTEGER FUNCTION hdr_hdl
INTEGER uhdr
INTEGER uhdr_len
TYPE (LAPI_ADDR_T) :: udata
INTEGER (KIND=LAPI_LONG_TYPE) :: udata_len      
INTEGER (KIND=LAPI_ADDR_TYPE) :: tgt_cntr
TYPE (LAPI_CNTR_T) :: org_cntr
TYPE (LAPI_CNTR_T) :: cmpl_cntr
INTEGER ierror

Descrição

Type of call: comunicação ponto-a-ponto (sem bloqueio)

Use este subroutine para transferir dados para uma tarefa de destino, em que é desejável executar um manipulador na tarefa de destino antes que a entrega de mensagens comece ou após a entrega ser concluída. LAPI_Amsend permite que o usuário forneça um manipulador de cabeçalho e manipulador de conclusão opcional. O manipulador de cabeçalho é usado para especificar o endereço de buffer de destino para a escrita dos dados, eliminando a necessidade de saber o endereço na tarefa de origem quando a subroutine é chamada.

Os dados do usuário (uhdr e udata) são enviados para a tarefa de destino. Uma vez que esses buffers não são mais necessários na tarefa de origem, o contador de origem é incrementado, o que indica a disponibilidade de buffers de origem para modificação. O uso da chamada LAPI_Xfer com o tipo LAPI_AM_XFER fornece o mesmo tipo de transferência, com a opção de usar um manipulador de conclusão de envio em vez do contador de origem para especificar disponibilidade de buffer.

Após a chegada do primeiro pacote de dados no alvo, o manipulador de cabeçalho do usuário é invocado. Note que um manipulador de cabeçalho deve ser fornecido pelo usuário porque ele retorna o endereço base do buffer no qual LAPI irá gravar os dados enviados a partir da tarefa de origem (udata). Veja RSCT para AIX 5L: Guia de Programação LAPI para uma exceção de otimização a esta exigência de que um endereço de buffer seja fornecido a LAPI para mensagens de pacotes únicos.

O manipulador de cabeçalho também fornece informações adicionais ao LAPI sobre a entrega de mensagens, como o manipulador de conclusão. LAPI_Amsend e chamadas semelhantes (como LAPI_Amsendv e correspondentes LAPI_Xfer transferências) também permitem que o usuário especifique as suas próprias informações de cabeçalho de mensagem, que está disponível para o manipulador de cabeçalho. O usuário pode também especificar um parâmetro de manipulador de conclusão de dentro do manipulador de cabeçalho. LAPI irá passar as informações para o manipulador de conclusão em execução.

Note que o manipulador de cabeçalho é executado inline pela thread executando o despachante LAPI. Por esta razão, o manipulador de cabeçalho deve ser não bloqueando porque nenhum outro progresso em mensagens será feito até que ele retorne. Sugere-se também que a execução do manipulador de cabeçalho seja simples e rápida. O manipulador de conclusão, por outro lado, é normalmente enfileirado para execução por um fio separado. É possível solicitar que o manipulador de conclusão seja executado inline. Veja RSCT para AIX 5L: Guia de Programação LAPI para obter mais informações sobre manipuladores de acabamento inline.

Se um manipulador de conclusão de conclusão não foi especificado (ou seja, configurado como LAPI_ADDR_NULL no FORTRAN ou seu conjunto de ponteiro para NULL em C), a chegada do pacote final faz com que o LAPI incremente o contador de destino na tarefa remota e envie uma mensagem interna de volta para a tarefa de origem. A mensagem causa o contador de conclusão (se ele não for NULL em C ou LAPI_ADDR_NULL no FORTRAN) para incrementar na tarefa de origem.

Se um manipulador de conclusão foi especificado, as etapas acima ocorram após o retorno do manipulador de conclusão. Para garantir que o manipulador de conclusão tenha executado no alvo, deve-se aguardar no balcão de conclusão. Veja RSCT para AIX 5L: Guia de Programação LAPI para um diagrama de sequência de tempo de eventos em uma chamada LAPI_Amsend .

Detalhes do usuário

Como mencionado acima, o usuário deve fornecer o endereço de um manipulador de cabeçalho para ser executado no destino mediante a chegada do primeiro pacote de dados. A assinatura do manipulador de cabeçalho é a seguinte:
void *hdr_hndlr(lapi_handle_t *hndl, void *uhdr, uint *uhdr_len, ulong *msg_len, 
               compl_hndlr_t **cmpl_hndlr, void **user_info);
O valor retornado pelo manipulador de cabeçalho é interpretado por LAPI como um endereço para a escrita dos dados do usuário (udata) que foi passada para a chamada LAPI_Amsend . Os parâmetros uhdr e uhdr_len são transmitidos por LAPI para o manipulador de cabeçalho e contêm as informações passadas pelo usuário para os parâmetros correspondentes da chamada LAPI_Amsend .

Uso de LAPI_Addr_set

Os endereços remotos são comumente trocados por meio da emissão de um chamado coletivo LAPI_Address_init dentro de alguns passos de inicializar LAPI. A LAPI também fornece o mecanismo LAPI_Addr_set , pelo qual os usuários podem registrar um ou mais endereços de manipulador de cabeçalho em uma tabela, associando um valor de índice a cada endereço. Esse índice pode então ser passado para LAPI_Amsend em vez de um endereço real. No lado alvo, LAPI usará o índice para obter o endereço do manipulador de cabeçalho. Observe que, se todas as tarefas utilizarem o mesmo índice para seu manipulador de cabeçalho, a comunicação coletiva inicial poderá ser evitada. Cada tarefa simplesmente registra seu próprio endereço de manipulador de cabeçalho usando o índice conhecido. Em seguida, em quaisquer chamadas LAPI_Amsend , o índice reservado pode ser passado para o parâmetro de endereço do manipulador de cabeçalho.

Função do manipulador de cabeçalho

O usuário, opcionalmente, retorna o endereço de uma função de manipulador de conclusão por meio do parâmetro cmpl_hndlr e um parâmetro manipulador de conclusão através do parâmetro user_info . O endereço passado através do parâmetro user_info pode referir-se à memória contendo um datatype definido pelo usuário e, em seguida, escalar para o tipo apropriado a partir de dentro do manipulador de conclusão se desejar.

A assinatura para um manipulador de conclusão de usuário é a seguinte:
typedef void (compl_hndlr_t)(lapi_handle_t *hndl, void *completion_param);
O argumento retornado por referência através do membro user_info do manipulador de cabeçalho do usuário será passado para o argumento completion_param do manipulador de conclusão do usuário. Veja os Exemplos de C para um exemplo de configuração do manipulador de conclusão e parâmetro no manipulador de cabeçalho.

Como mencionado acima, o valor retornado pelo manipulador de cabeçalho deve ser um endereço para a escrita dos dados do usuário enviados a partir da tarefa de origem. Há uma exceção para essa regra. No caso de uma mensagem de pacote único, LAPI passa o endereço do pacote no FIFO do recebimento, permitindo que toda a mensagem seja consumida dentro do manipulador de cabeçalho. Neste caso, o manipulador de cabeçalho deve retornar NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN) para que o LAPI não copie a mensagem para um buffer de destino. Veja RSCT para AIX 5L: Guia de Programação LAPI para obter mais informações (incluindo um manipulador de cabeçalho de amostra que usa este método para recuperação rápida de uma mensagem de um pacote único).

Passando informações adicionais através de lapi_return_info_t

O LAPI permite que informações adicionais sejam passadas e retornadas do manipulador de cabeçalho passando um ponteiro para lapi_return_info_t através do argumento msg_len . No retorno de um manipulador de cabeçalho que é invocado por uma chamada para LAPI_Amsend, o membro ret_flags de lapi_return_info_t pode conter um desses valores: LAPI_NORMAL (o padrão), LAPI_SEND_REPLY (para executar o manipulador de conclusão inline), ou LAPI_LOCAL_STATE (nenhuma resposta é enviada). O membro dgsp_handle de lapi_return_info_t não deve ser usado em conjunto com LAPI_Amsend.

Para uma descrição completa do tipo lapi_return_info_t , consulte RSCT para AIX 5L: Guia de Programação LAPI

execução inline de manipuladores de conclusão

Em operação normal, LAPI usa uma thread separada para executar manipuladores de conclusão de usuário. Após o pacote final chegar, os ponteiros do manipulador de conclusão são colocados em uma fila para serem tratados por este encadeamento. Por motivos de desempenho, o usuário pode solicitar que um determinado manipulador de conclusão seja executado inline em vez de ser colocado nesta fila atrás de outros manipuladores de acabamento. Este mecanismo dá aos usuários um maior grau de controle na priorização da execução do manipulador de conclusão para mensagens de desempenho crítico.

LAPI coloca sem restrições os manipuladores de conclusão que são executados "normalmente" (ou seja, pelo encadeamento do manipulador de conclusão). Os manipuladores de acabamento inline devem ser curtos e não devem bloquear, pois nenhum progresso pode ser feito enquanto a thread principal estiver executando o manipulador. O usuário deve usar o cuidado com os manipuladores de conclusão de inline para que as filas internas da LAPI não se preencham enquanto aguarda o manipulador ser concluído. As operações de E/S não devem ser executadas com um manipulador de conclusão inline.

Parâmetros

INPUT
hndl
Especifica a alça LAPI.
tgt
Especifica o ID da tarefa da tarefa de destino. O valor deste parâmetro deve estar na faixa 0 < = tgt < NUM_TASKS.
hdr_hdl
Especifica o ponteiro para a função de manipulador de cabeçalho remoto a ser invocado no destino. O valor deste parâmetro pode tirar uma alça de endereço que já foi registrado usando LAPI_Addr_set. O valor deste parâmetro não pode ser NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN).
uhdr
Especifica o ponteiro para os dados do cabeçalho do usuário. Esses dados serão passados para o manipulador de cabeçalho do usuário no destino. Se uhdr_len for 0, O valor deste parâmetro pode ser NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN).
uhdr_len
Especifica o comprimento do cabeçalho do usuário. O valor deste parâmetro deve ser um múltiplo do tamanho word do processador no intervalo 0 < = uhdr_len < = MAX_UHDR_SZ.
udata
Especifica o ponteiro para os dados do usuário. Se udata_len for 0, O valor deste parâmetro pode ser NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN).
udata_len
Especifica o comprimento dos dados do usuário em bytes. O valor deste parâmetro deve estar na faixa 0 < = udata_len < = o valor da constante LAPI LAPI_MAX_MSG_SZ.
entrada/saída
tgt_cntr
Especifica o endereço do contador de destino. O contador de destino é incrementado após o manipulador de conclusão (se especificado) concluir ou após a conclusão da transferência de dados. Se o valor deste parâmetro for NULL (em C) ou LAPI_ADDR_NULL (no FORTRAN), o contador de destino não será atualizado.
org_cntr
Especifica o endereço do contador de origem (em C) ou o contador de origem (em FORTRAN). O contador de origem é incrementado após os dados serem copiados para fora do endereço de origem (em C) ou da origem (em FORTRAN). Se o valor deste parâmetro for NULL (em C) ou LAPI_ADDR_NULL (no FORTRAN), o contador de origem não será atualizado.
cmpl_cntr
Especifica o contador na origem que significa conclusão do manipulador de conclusão. Ele é atualizado uma vez que o manipulador de conclusão é concluído. Se nenhum manipulador de conclusão for especificado, o contador será incrementado na conclusão da entrega de mensagens. Se o valor deste parâmetro for NULL (em C) ou LAPI_ADDR_NULL (no FORTRAN), o contador de conclusão não será atualizado.
SAÍDA
ierror
Especifica um código de retorno FORTRAN. Este é sempre o último parâmetro.

Valores De Retorno

LAPI_SUCESSO
Indica que a chamada de função foi concluída com sucesso.
LAPI_ERR_DATA_LEN
Indica que o valor de udata_len é maior do que o valor da constante LAPI LAPI_MAX_MSG_SZ.
LAPI_ERR_HDR_HNDLR_NULL
Indica que o valor do hdr_hdl passado em é NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN).
LAPI_ERR_HNDL_INVÁLIDA
Indica que o hndl passado em não é válido (não inicializado ou em estado finalizado).
LAPI_ERR_ORG_ADDR_NULL
Indica que o valor do parâmetro udata passado em é NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN), mas o valor de udata_len é maior que 0.
LAPI_ERR_TGT
Indica que o tgt passado em está fora do intervalo de tarefas definidas no job.
LAPI_ERR_TGT_PURGED
Indica que a subroutine retornou mais cedo porque LAPI_Purge_totask() foi chamada.
LAPI_ERR_UHDR_LEN
Indica que o valor uhdr_len passado em é maior do que MAX_UHDR_SZ ou não é um múltiplo do tamanho do doubleword do processador.
LAPI_ERR_UHDR_NULL
Indica que o uhdr passado em é NULL (em C) ou LAPI_ADDR_NULL (em FORTRAN), mas uhdr_len não é 0.

Exemplos de C

Para enviar uma mensagem ativa e depois aguardar no balcão de conclusão:
 
/* header handler routine to execute on target task */
void *hdr_hndlr(lapi_handle_t *hndl, void *uhdr, uint *uhdr_len, 
               ulong *msg_len, compl_hndlr_t **cmpl_hndlr, 
		void **user_info)
{
/* set completion handler pointer and other information */
/* return base address for LAPI to begin its data copy  */
}

{
    lapi_handle_t hndl;                      /* the LAPI handle                     */
    int           task_id;                   /* the LAPI task ID                    */ 
    int           num_tasks;                 /* the total number of tasks           */
    void         *hdr_hndlr_list[NUM_TASKS]; /* the table of remote header handlers */
    int           buddy;                     /* the communication partner           */
    lapi_cntr_t   cmpl_cntr;                 /* the completion counter              */
    int           data_buffer[DATA_LEN];     /* the data to transfer                */

    .
    .
    .      
    /* retrieve header handler addresses */
    LAPI_Address_init(hndl, (void *)&hdr_hndlr, hdr_hndlr_list);
      
      
    /*
    ** up to this point, all instructions have executed on all 
    ** tasks. we now begin differentiating tasks.
    */
    if ( sender ) {                   /* origin task */
      
        /* initialize data buffer, cmpl_cntr, etc.   */
        .	
        .
        .      
        /* synchronize before starting data transfer */
        LAPI_Gfence(hndl);
      
	    
        LAPI_Amsend(hndl, buddy, (void *)hdr_hndlr_list[buddy], NULL, 
                    0,&(data_buffer[0]),DATA_LEN*(sizeof(int)),
                    NULL, NULL, cmpl_cntr);
      
        /* Wait on completion counter before continuing. Completion   */ 
        /* counter will update when message completes at target.      */
      
    } else {                                              /* receiver */
        .   
        .
        .      
        /* to match the origin's synchronization before data transfer */
        LAPI_Gfence(hndl);
    }

    .
    .
    .
}

Para uma listagem completa do programa, consulte RSCT para AIX 5L: Guia de Programação LAPI. Código de amostra ilustrando a chamada LAPI_Amsend pode ser encontrado nos arquivos de amostra LAPI. Veja RSCT para AIX 5L: Guia de Programação LAPI para obter mais informações sobre os programas de amostra embarcados com LAPI.

Local

/usr/lib/liblapi_r.a