Rate This Document
Findability
Accuracy
Completeness
Readability

kupl_shm_allreduce_init

Initialize AllReduce between processes.

Interface Definition

int kupl_shm_allreduce_init(const void *sendbuf, void *recvbuf, int count, kupl_shm_datatype_t datatype, kupl_shm_reduce_op_t op, kupl_shm_comm_h comm, kupl_shm_request_t *request);

Environment Variables

AllReduce can use KUPL_SHM_ALLREDUCE_ALGORITHM to specify algorithms.

Possible values:

  • 0: (default) auto_tuning
  • 1: linear
  • 2: rb (rh_rd)

Parameters

Table 1 Parameter definition

Parameter

Type

Description

Input/Output

sendbuf

const void *

Required send buffer.

Input

recvbuf

void *

Required recv buffer.

Input

count

int

Required send count.

Input

datatype

kupl_shm_datatype_t

Required data type, which can be set to KUPL_SHM_DATATYPE_CHAR, KUPL_SHM_DATATYPE_INT, KUPL_SHM_DATATYPE_LONG, KUPL_SHM_DATATYPE_FLOAT, or KUPL_SHM_DATATYPE_DOUBLE.

Input

op

kupl_shm_reduce_op_t

Required reduction operation, which can be set to KUPL_SHM_REDUCE_OP_SUM.

Input

comm

kupl_shm_comm_h

Required KUPL communicator.

Input

request

kupl_shm_request_t *

Generated persistent request.

Output

Return Value

  • Success: KUPL_OK
  • Failure: KUPL_ERROR

Examples

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdio.h>
#include <mpi.h>
#include <unistd.h>
#include "kupl.h"

// Callback 1 required for creating a KUPL communicator.
static int oob_barrier_callback(void *group)
{
    return MPI_Barrier((MPI_Comm)group);
}
// Callback 2 required for creating a KUPL communicator.
static int oob_allgather_callback(const void *sendbuf, void *recvbuf, int size, void *group,
                                  kupl_shm_datatype_t datatype)
{
    switch (datatype) {
        case KUPL_SHM_DATATYPE_CHAR:
            return MPI_Allgather(sendbuf, size, MPI_CHAR, recvbuf, size, MPI_CHAR, (MPI_Comm)group);
        default:
            fprintf(stderr, "not support datatype");
            return KUPL_ERROR;
    }
}
int main(int argc, char *argv[])
{
    // Initialize the MPI environment.
    MPI_Init(&argc, &argv);
    MPI_Comm comm = MPI_COMM_WORLD;
    // Obtain the size of the MPI communicator.
    int world_size;
    MPI_Comm_size(comm, &world_size);
    // Obtain the rank of the process.
    int world_rank;
    MPI_Comm_rank(comm, &world_rank);
    // Obtain the PID.
    int pid = getpid();
    // Create a KUPL communicator.
    kupl_shm_oob_cb_t oob_cbs;
    kupl_shm_oob_cb_h oob_cbs_h = &oob_cbs;
    oob_cbs_h->oob_allgather = oob_allgather_callback;
    oob_cbs_h->oob_barrier = oob_barrier_callback;
    kupl_shm_comm_h kupl_comm;
    int ret = kupl_shm_comm_create(world_size, world_rank, pid, oob_cbs_h, (void *)comm, &kupl_comm);
    if (ret != KUPL_OK || kupl_comm == NULL) {
        fprintf(stderr, "kupl shm comm create failed: %d\n", ret);
        return -1;
    }
    kupl_shm_win_h win_send;
    kupl_shm_win_h win_recv;
    kupl_shm_win_h ompi_win_recv;
    void *sendbuf = NULL;
    void *recvbuf = NULL;
    void *ompibuf = NULL;
    int count = 16000;
    size_t buf_size = sizeof(int) * count;
    ret = kupl_shm_win_alloc(buf_size, kupl_comm, &sendbuf, &win_send);
    if (ret != KUPL_OK) {
        fprintf(stderr, "kupl sendbuf alloc failed: %d\n", ret);
        return -1;
    }
    ret = kupl_shm_win_alloc(buf_size, kupl_comm, &recvbuf, &win_recv);
    if (ret != KUPL_OK) {
        fprintf(stderr, "kupl recvbuf alloc failed: %d\n", ret);
        kupl_shm_win_free(win_send);
        win_send = NULL;
        return -1;
    }
    ret = kupl_shm_win_alloc(buf_size, kupl_comm, &ompibuf, &ompi_win_recv);
    if (ret != KUPL_OK) {
        fprintf(stderr, "kupl ompibuf alloc failed: %d\n", ret);
        kupl_shm_win_free(win_send);
        kupl_shm_win_free(win_recv);
        win_send = NULL;
        win_recv = NULL;
        return -1;
    }
    auto *t_sendbuf = static_cast<int *>(sendbuf);
    auto *t_recvbuf = static_cast<int *>(recvbuf);
    auto *t_ompibuf = static_cast<int *>(ompibuf);
    for (int i = 0; i < count; i++) {
        t_sendbuf[i] = world_rank + i;
    }
    kupl_shm_request_h request;
    MPI_Barrier(comm);
    kupl_shm_allreduce_init(sendbuf, recvbuf, count, KUPL_SHM_DATATYPE_INT, KUPL_SHM_REDUCE_OP_SUM, kupl_comm,
                            &request);
    kupl_shm_request_start(request);
    kupl_shm_request_wait(request);
    kupl_shm_request_free(request);
    MPI_Barrier(comm);
    MPI_Allreduce(sendbuf, ompibuf, count, MPI_INT, MPI_SUM, comm);
    int check = 0;
    for (int i = 0; i < count; i++) {
        if (t_recvbuf[i] != t_ompibuf[i]) {
            check = 1;
            break;
        }
    }
    int result = 0;
    MPI_Reduce(&check, &result, 1, MPI_INT, MPI_SUM, 0, comm);
    if (result == 0) {
        printf("check success\n");
    } else {
        printf("check failed\n");
    }
    kupl_shm_win_free(win_send);
    kupl_shm_win_free(win_recv);
    kupl_shm_win_free(ompi_win_recv);
    win_send = NULL;
    win_recv = NULL;
    ompi_win_recv = NULL;
    kupl_shm_comm_destroy(kupl_comm);
    MPI_Finalize();
    return 0;
}

The execution result is as follows:

check success

The preceding example demonstrates the process of KUPL AllReduce. The kupl_shm_allreduce_init function is used to initialize the AllReduce request.